Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Starlight <> Ethereum: Rewards mapping #761

Draft
wants to merge 56 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
715712c
WIP does not compile, needs cherry pick AggregateMessageOrigin
tmpolaczyk Nov 5, 2024
039944f
Add eth outbound queue and system pallets
tmpolaczyk Nov 5, 2024
74c1e45
Use fork branch tomasz-generic-aggregate-message-origin
tmpolaczyk Nov 5, 2024
8de7e4e
Update Cargo.lock
tmpolaczyk Nov 5, 2024
abcfc96
Fix outdated fork branches
tmpolaczyk Nov 5, 2024
64dd2e7
Fix tests and benchmarks
tmpolaczyk Nov 6, 2024
d4907e3
Merge remote-tracking branch 'origin/master' into tomasz-generic-aggr…
tmpolaczyk Nov 6, 2024
d52fc32
Fix compilation and toml
tmpolaczyk Nov 6, 2024
78ba7d2
WIP root_test_send_msg_to_eth
tmpolaczyk Nov 7, 2024
676792c
Use custom Command enum and do_process_message impl
tmpolaczyk Nov 7, 2024
2286b76
Create validate trait
tmpolaczyk Nov 7, 2024
0873ec0
Fix tests
tmpolaczyk Nov 7, 2024
76b393e
Fix unused variable
tmpolaczyk Nov 7, 2024
2d4ae6d
Fix toml
tmpolaczyk Nov 7, 2024
37f405f
Add integration test
tmpolaczyk Nov 7, 2024
153a76e
pnpm lint and fmt
tmpolaczyk Nov 7, 2024
88c21ca
typescript-api
tmpolaczyk Nov 7, 2024
2e45e28
Also support original Command enum
tmpolaczyk Nov 8, 2024
f6511b6
typescript-api
tmpolaczyk Nov 8, 2024
153c28a
Add test using snowbridge message
tmpolaczyk Nov 8, 2024
b68d289
Add different origin for custom snowbridge messages vs original ones
tmpolaczyk Nov 11, 2024
ec385d6
add initial ReportSlashes variant
Agusrodri Nov 12, 2024
2a8d873
PR review
tmpolaczyk Nov 12, 2024
d658039
Merge remote-tracking branch 'origin/master' into tomasz-generic-aggr…
tmpolaczyk Nov 12, 2024
647b875
Fix tests
tmpolaczyk Nov 12, 2024
176df0f
polkadot-sdk branch merged, use stable2407 again
tmpolaczyk Nov 12, 2024
90c2446
typescript-api
tmpolaczyk Nov 12, 2024
4d0a6ae
small PoC for sending slashes message on_initialize
Agusrodri Nov 13, 2024
f8b9604
minor fixes
Agusrodri Nov 13, 2024
72f296c
Test message limits: max numMsg and msgSize
tmpolaczyk Nov 13, 2024
91544be
Merge remote-tracking branch 'origin/tomasz-generic-aggregate-message…
Agusrodri Nov 13, 2024
cd341db
Merge remote-tracking branch 'origin/master' into tomasz-generic-aggr…
tmpolaczyk Nov 20, 2024
23124e3
Add benchmarks
tmpolaczyk Nov 20, 2024
804fafd
fmt
tmpolaczyk Nov 20, 2024
32d3fe2
Fix accidental refactor
tmpolaczyk Nov 20, 2024
d56cfc6
Merge remote-tracking branch 'origin/tomasz-generic-aggregate-message…
Agusrodri Nov 20, 2024
679fb69
typescript-api
tmpolaczyk Nov 20, 2024
cc8622c
only map rewards
Agusrodri Nov 20, 2024
54ec73d
PR comments
tmpolaczyk Nov 21, 2024
d0b70c3
Merge remote-tracking branch 'origin/master' into tomasz-generic-aggr…
tmpolaczyk Nov 21, 2024
53d8847
Merge branch 'master' into tomasz-generic-aggregate-message-origin
tmpolaczyk Nov 22, 2024
1622364
Merge remote-tracking branch 'origin/master' into tomasz-generic-aggr…
tmpolaczyk Nov 25, 2024
63bebcc
Copy
tmpolaczyk Nov 25, 2024
f0aec95
refactor mapping and add test
Agusrodri Nov 25, 2024
30db868
Merge remote-tracking branch 'origin/tomasz-generic-aggregate-message…
Agusrodri Nov 25, 2024
d3e42fa
fix match pattern
Agusrodri Nov 25, 2024
a81c935
start adding runtime-api
Agusrodri Nov 26, 2024
b79e861
Merge remote-tracking branch 'origin/master' into agustin-map-rewards
Agusrodri Nov 26, 2024
8ccc5a7
more progress on runtime apis
Agusrodri Nov 26, 2024
19a605c
add test for merkle proofs
Agusrodri Nov 27, 2024
9c76825
Merge remote-tracking branch 'origin/master' into agustin-map-rewards
Agusrodri Nov 27, 2024
a66ec7b
fmt
Agusrodri Nov 27, 2024
cbb78dc
fix external-validators-rewards mock
Agusrodri Nov 27, 2024
213f7f4
toml fmt
Agusrodri Nov 27, 2024
78680c5
rust fmt
Agusrodri Nov 27, 2024
7d8ec4f
add more checks to rust test
Agusrodri Nov 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pallet-data-preservers-runtime-api = { path = "pallets/data-preservers/runtime-a
pallet-external-validator-slashes = { path = "pallets/external-validator-slashes", default-features = false }
pallet-external-validators = { path = "pallets/external-validators", default-features = false }
pallet-external-validators-rewards = { path = "pallets/external-validators-rewards", default-features = false }
pallet-external-validators-rewards-runtime-api = { path = "pallets/external-validators-rewards/runtime-api", default-features = false }
pallet-inflation-rewards = { path = "pallets/inflation-rewards", default-features = false }
pallet-initializer = { path = "pallets/initializer", default-features = false }
pallet-invulnerables = { path = "pallets/invulnerables", default-features = false }
Expand Down Expand Up @@ -260,9 +261,11 @@ xcm-runtime-apis = { git = "https://github.com/moondance-labs/polkadot-sdk", bra

# Bridges (wasm)
alloy-sol-types = { version = "0.4.2", default-features = false }
bridge-hub-common = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-stable2407", default-features = false }
milagro-bls = { package = "snowbridge-milagro-bls", version = "1.5.4", default-features = false }
snowbridge-beacon-primitives = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-stable2409", default-features = false }
snowbridge-core = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-stable2409", default-features = false }
snowbridge-outbound-queue-merkle-tree = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-stable2409", default-features = false }
snowbridge-pallet-ethereum-client = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-stable2409", default-features = false }
snowbridge-pallet-inbound-queue = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-stable2409", default-features = false }
snowbridge-pallet-inbound-queue-fixtures = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-stable2409", default-features = false }
Expand Down
13 changes: 12 additions & 1 deletion pallets/external-validators-rewards/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ targets = [ "x86_64-unknown-linux-gnu" ]
workspace = true

[dependencies]
log = { workspace = true }
parity-scale-codec = { workspace = true }
scale-info = { workspace = true, features = [ "derive" ] }

frame-support = { workspace = true }
frame-system = { workspace = true }
sp-core = { workspace = true }
sp-runtime = { workspace = true }
sp-staking = { workspace = true }
sp-std = { workspace = true }
tp-bridge = { workspace = true }
tp-traits = { workspace = true }

frame-benchmarking = { workspace = true }
Expand All @@ -29,11 +32,13 @@ pallet-balances = { workspace = true, optional = true }
pallet-session = { workspace = true, features = [ "historical" ] }
runtime-parachains = { workspace = true }

snowbridge-core = { workspace = true }
snowbridge-outbound-queue-merkle-tree = { workspace = true }

polkadot-primitives = { workspace = true }

[dev-dependencies]
pallet-timestamp = { workspace = true }
sp-core = { workspace = true }
sp-io = { workspace = true }

[features]
Expand All @@ -42,18 +47,22 @@ std = [
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"log/std",
"pallet-balances/std",
"pallet-session/std",
"pallet-timestamp/std",
"parity-scale-codec/std",
"polkadot-primitives/std",
"runtime-parachains/std",
"scale-info/std",
"snowbridge-core/std",
"snowbridge-outbound-queue-merkle-tree/std",
"sp-core/std",
"sp-io/std",
"sp-runtime/std",
"sp-staking/std",
"sp-std/std",
"tp-bridge/std",
"tp-traits/std",
]
runtime-benchmarks = [
Expand All @@ -64,8 +73,10 @@ runtime-benchmarks = [
"pallet-timestamp/runtime-benchmarks",
"polkadot-primitives/runtime-benchmarks",
"runtime-parachains/runtime-benchmarks",
"snowbridge-core/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
"tp-bridge/runtime-benchmarks",
"tp-traits/runtime-benchmarks",
]

Expand Down
28 changes: 28 additions & 0 deletions pallets/external-validators-rewards/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "pallet-external-validators-rewards-runtime-api"
authors = { workspace = true }
description = "Runtime API definition of pallet-external-validators-rewards"
edition = "2021"
license = "GPL-3.0-only"
version = "0.1.0"

[package.metadata.docs.rs]
targets = [ "x86_64-unknown-linux-gnu" ]

[lints]
workspace = true

[dependencies]
parity-scale-codec = { workspace = true }
snowbridge-outbound-queue-merkle-tree = { workspace = true }
sp-api = { workspace = true }
sp-core = { workspace = true }

[features]
default = [ "std" ]
std = [
"parity-scale-codec/std",
"snowbridge-outbound-queue-merkle-tree/std",
"sp-api/std",
"sp-core/std",
]
32 changes: 32 additions & 0 deletions pallets/external-validators-rewards/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) Moondance Labs Ltd.
// This file is part of Tanssi.

// Tanssi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Tanssi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Tanssi. If not, see <http://www.gnu.org/licenses/>

//! Runtime API for External Validators Rewards pallet

#![cfg_attr(not(feature = "std"), no_std)]

use snowbridge_outbound_queue_merkle_tree::MerkleProof;

sp_api::decl_runtime_apis! {
pub trait ExternalValidatorsRewardsApi<AccountId, EraIndex>
where
AccountId: parity_scale_codec::Codec,
EraIndex: parity_scale_codec::Codec,
{
fn generate_rewards_merkle_proof(account_id: AccountId, era_index: EraIndex) -> Option<MerkleProof>;
fn verify_rewards_merkle_proof(merkle_proof: MerkleProof) -> bool;
}
}
122 changes: 121 additions & 1 deletion pallets/external-validators-rewards/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,24 @@ pub use pallet::*;

use {
frame_support::traits::{Defensive, Get, ValidatorSet},
parity_scale_codec::Encode,
polkadot_primitives::ValidatorIndex,
runtime_parachains::session_info,
snowbridge_core::ChannelId,
snowbridge_outbound_queue_merkle_tree::{merkle_proof, merkle_root, verify_proof, MerkleProof},
sp_core::H256,
sp_runtime::traits::Hash,
sp_staking::SessionIndex,
sp_std::collections::btree_set::BTreeSet,
sp_std::vec,
sp_std::vec::Vec,
tp_bridge::{Command, DeliverMessage, Message, ValidateMessage},
};

#[frame_support::pallet]
pub mod pallet {
use {
frame_support::pallet_prelude::*, sp_std::collections::btree_map::BTreeMap,
super::*, frame_support::pallet_prelude::*, sp_std::collections::btree_map::BTreeMap,
tp_traits::EraIndexProvider,
};

Expand All @@ -64,6 +72,16 @@ pub mod pallet {
/// The amount of era points given by dispute voting on a candidate.
#[pallet::constant]
type DisputeStatementPoints: Get<u32>;

type TimestampProvider: Get<u64>;

type Hashing: Hash<Output = H256>;

type ValidateMessage: ValidateMessage;

type OutboundQueue: DeliverMessage<
Ticket = <<Self as pallet::Config>::ValidateMessage as ValidateMessage>::Ticket,
>;
}

#[pallet::pallet]
Expand Down Expand Up @@ -104,6 +122,63 @@ pub mod pallet {
}
})
}

pub fn generate_era_rewards_utils(
era_index: EraIndex,
maybe_account_id_check: Option<T::AccountId>,
) -> Option<(H256, Vec<H256>, Option<u64>, u128)> {
let era_rewards = RewardPointsForEra::<T>::get(&era_index);
let total_points: u128 = era_rewards.total as u128;
let mut leaves = Vec::with_capacity(era_rewards.individual.len());
let mut leaf_index = None;

for (index, (account_id, reward_points)) in era_rewards.individual.iter().enumerate() {
let encoded = (account_id, reward_points).encode();
let hashed = <T as Config>::Hashing::hash(&encoded);
leaves.push(hashed);

if let Some(ref check_account_id) = maybe_account_id_check {
if account_id == check_account_id {
leaf_index = Some(index as u64);
}
}
}

// If a specific account is checked but not found, return None
if maybe_account_id_check.is_some() && leaf_index.is_none() {
log::error!(
target: "ext_validators_rewards",
"AccountId {:?} not found for era {:?}!",
maybe_account_id_check,
era_index
);
return None;
}

let rewards_merkle_root =
merkle_root::<<T as Config>::Hashing, _>(leaves.iter().cloned());
Some((rewards_merkle_root, leaves, leaf_index, total_points))
}

pub fn generate_rewards_merkle_proof(
account_id: T::AccountId,
era_index: EraIndex,
) -> Option<MerkleProof> {
let (_, leaves, leaf_index, _) =
Self::generate_era_rewards_utils(era_index, Some(account_id))?;
leaf_index
.map(|index| merkle_proof::<<T as Config>::Hashing, _>(leaves.into_iter(), index))
}

pub fn verify_rewards_merkle_proof(merkle_proof: MerkleProof) -> bool {
verify_proof::<<T as Config>::Hashing, _, _>(
&merkle_proof.root,
merkle_proof.proof,
merkle_proof.number_of_leaves,
merkle_proof.leaf_index,
merkle_proof.leaf,
)
}
}

impl<T: Config> tp_traits::OnEraStart for Pallet<T> {
Expand All @@ -115,6 +190,51 @@ pub mod pallet {
RewardPointsForEra::<T>::remove(era_index_to_delete);
}
}

impl<T: Config> tp_traits::OnEraEnd for Pallet<T> {
fn on_era_end(era_index: EraIndex) {
if let Some((rewards_merkle_root, _, _, total_points)) =
Self::generate_era_rewards_utils(era_index, None)
{
let command = Command::ReportRewards {
timestamp: T::TimestampProvider::get(),
era_index,
total_points,
// TODO: manage this in a proper way.
tokens_inflated: 0u128,
rewards_merkle_root,
};

let channel_id: ChannelId = snowbridge_core::PRIMARY_GOVERNANCE_CHANNEL;

let outbound_message = Message {
id: None,
channel_id,
command,
};

// Validate and deliver the message
match T::ValidateMessage::validate(&outbound_message) {
Ok((ticket, _fee)) => {
if let Err(err) = T::OutboundQueue::deliver(ticket) {
log::error!(target: "xcm::ethereum_blob_exporter", "OutboundQueue delivery of message failed. {err:?}");
}
}
Err(err) => {
log::error!(target: "xcm::ethereum_blob_exporter", "OutboundQueue validation of message failed. {err:?}");
}
}
} else {
// Unreachable, this should never happen as we are sending
// None as the second param in Self::generate_era_rewards_utils.
log::error!(
target: "ext_validators_rewards",
"Outbound message not sent for era {:?}!",
era_index
);
}
}
}
}

/// Rewards validators for participating in parachains with era points in pallet-staking.
Expand Down
Loading
Loading