mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 22:41:02 +00:00
Make BEEFY payload extensible (#10307)
* make BEEFY payload extensible * cargo fmt * cargo fmt * remove generic payload param in beefy-primitives * cargo fmt * Apply suggestions from code review Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * adds Paylaod Type * remove hex * fix tests * Apply suggestions from code review Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * use binary_search_by to sort * Payload::new() * fix tests * Apply suggestions from code review Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * fix tests * cargo fmt * fix get_decoded * fix test Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
This commit is contained in:
Generated
+1
@@ -535,6 +535,7 @@ dependencies = [
|
||||
name = "beefy-primitives"
|
||||
version = "4.0.0-dev"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"hex-literal",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
|
||||
@@ -30,7 +30,7 @@ use wasm_timer::Instant;
|
||||
|
||||
use beefy_primitives::{
|
||||
crypto::{Public, Signature},
|
||||
MmrRootHash, VoteMessage,
|
||||
VoteMessage,
|
||||
};
|
||||
|
||||
use crate::keystore::BeefyKeystore;
|
||||
@@ -142,9 +142,7 @@ where
|
||||
sender: &PeerId,
|
||||
mut data: &[u8],
|
||||
) -> ValidationResult<B::Hash> {
|
||||
if let Ok(msg) =
|
||||
VoteMessage::<MmrRootHash, NumberFor<B>, Public, Signature>::decode(&mut data)
|
||||
{
|
||||
if let Ok(msg) = VoteMessage::<NumberFor<B>, Public, Signature>::decode(&mut data) {
|
||||
let msg_hash = twox_64(data);
|
||||
let round = msg.commitment.block_number;
|
||||
|
||||
@@ -178,9 +176,7 @@ where
|
||||
fn message_expired<'a>(&'a self) -> Box<dyn FnMut(B::Hash, &[u8]) -> bool + 'a> {
|
||||
let known_votes = self.known_votes.read();
|
||||
Box::new(move |_topic, mut data| {
|
||||
let msg = match VoteMessage::<MmrRootHash, NumberFor<B>, Public, Signature>::decode(
|
||||
&mut data,
|
||||
) {
|
||||
let msg = match VoteMessage::<NumberFor<B>, Public, Signature>::decode(&mut data) {
|
||||
Ok(vote) => vote,
|
||||
Err(_) => return true,
|
||||
};
|
||||
@@ -214,9 +210,7 @@ where
|
||||
return do_rebroadcast
|
||||
}
|
||||
|
||||
let msg = match VoteMessage::<MmrRootHash, NumberFor<B>, Public, Signature>::decode(
|
||||
&mut data,
|
||||
) {
|
||||
let msg = match VoteMessage::<NumberFor<B>, Public, Signature>::decode(&mut data) {
|
||||
Ok(vote) => vote,
|
||||
Err(_) => return true,
|
||||
};
|
||||
@@ -237,9 +231,11 @@ mod tests {
|
||||
use sc_network_test::Block;
|
||||
use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
|
||||
|
||||
use beefy_primitives::{crypto::Signature, Commitment, MmrRootHash, VoteMessage, KEY_TYPE};
|
||||
|
||||
use crate::keystore::{tests::Keyring, BeefyKeystore};
|
||||
use beefy_primitives::{
|
||||
crypto::Signature, known_payload_ids, Commitment, MmrRootHash, Payload, VoteMessage,
|
||||
KEY_TYPE,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -345,10 +341,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn sign_commitment<BN: Encode, P: Encode>(
|
||||
who: &Keyring,
|
||||
commitment: &Commitment<BN, P>,
|
||||
) -> Signature {
|
||||
fn sign_commitment<BN: Encode>(who: &Keyring, commitment: &Commitment<BN>) -> Signature {
|
||||
let store: SyncCryptoStorePtr = std::sync::Arc::new(LocalKeystore::in_memory());
|
||||
SyncCryptoStore::ecdsa_generate_new(&*store, KEY_TYPE, Some(&who.to_seed())).unwrap();
|
||||
let beefy_keystore: BeefyKeystore = Some(store).into();
|
||||
@@ -362,11 +355,8 @@ mod tests {
|
||||
let sender = sc_network::PeerId::random();
|
||||
let mut context = TestContext;
|
||||
|
||||
let commitment = Commitment {
|
||||
payload: MmrRootHash::default(),
|
||||
block_number: 3_u64,
|
||||
validator_set_id: 0,
|
||||
};
|
||||
let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, MmrRootHash::default().encode());
|
||||
let commitment = Commitment { payload, block_number: 3_u64, validator_set_id: 0 };
|
||||
|
||||
let signature = sign_commitment(&Keyring::Alice, &commitment);
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ use sp_runtime::traits::{Block, NumberFor};
|
||||
use parking_lot::Mutex;
|
||||
|
||||
/// Stream of signed commitments returned when subscribing.
|
||||
pub type SignedCommitment<Block> =
|
||||
beefy_primitives::SignedCommitment<NumberFor<Block>, beefy_primitives::MmrRootHash>;
|
||||
pub type SignedCommitment<Block> = beefy_primitives::SignedCommitment<NumberFor<Block>>;
|
||||
|
||||
/// Stream of signed commitments returned when subscribing.
|
||||
type SignedCommitmentStream<Block> = TracingUnboundedReceiver<SignedCommitment<Block>>;
|
||||
|
||||
@@ -53,14 +53,14 @@ fn threshold(authorities: usize) -> usize {
|
||||
authorities - faulty
|
||||
}
|
||||
|
||||
pub(crate) struct Rounds<Hash, Number> {
|
||||
rounds: BTreeMap<(Hash, Number), RoundTracker>,
|
||||
pub(crate) struct Rounds<Payload, Number> {
|
||||
rounds: BTreeMap<(Payload, Number), RoundTracker>,
|
||||
validator_set: ValidatorSet<Public>,
|
||||
}
|
||||
|
||||
impl<H, N> Rounds<H, N>
|
||||
impl<P, N> Rounds<P, N>
|
||||
where
|
||||
H: Ord + Hash,
|
||||
P: Ord + Hash,
|
||||
N: Ord + AtLeast32BitUnsigned + MaybeDisplay,
|
||||
{
|
||||
pub(crate) fn new(validator_set: ValidatorSet<Public>) -> Self {
|
||||
@@ -70,8 +70,8 @@ where
|
||||
|
||||
impl<H, N> Rounds<H, N>
|
||||
where
|
||||
H: Ord + Hash,
|
||||
N: Ord + AtLeast32BitUnsigned + MaybeDisplay,
|
||||
H: Ord + Hash + Clone,
|
||||
N: Ord + AtLeast32BitUnsigned + MaybeDisplay + Clone,
|
||||
{
|
||||
pub(crate) fn validator_set_id(&self) -> ValidatorSetId {
|
||||
self.validator_set.id
|
||||
@@ -81,9 +81,9 @@ where
|
||||
self.validator_set.validators.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn add_vote(&mut self, round: (H, N), vote: (Public, Signature)) -> bool {
|
||||
pub(crate) fn add_vote(&mut self, round: &(H, N), vote: (Public, Signature)) -> bool {
|
||||
if self.validator_set.validators.iter().any(|id| vote.0 == *id) {
|
||||
self.rounds.entry(round).or_default().add_vote(vote)
|
||||
self.rounds.entry(round.clone()).or_default().add_vote(vote)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -179,7 +179,7 @@ mod tests {
|
||||
let mut rounds = Rounds::<H256, NumberFor<Block>>::new(validators);
|
||||
|
||||
assert!(rounds.add_vote(
|
||||
(H256::from_low_u64_le(1), 1),
|
||||
&(H256::from_low_u64_le(1), 1),
|
||||
(Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed"))
|
||||
));
|
||||
|
||||
@@ -187,21 +187,21 @@ mod tests {
|
||||
|
||||
// invalid vote
|
||||
assert!(!rounds.add_vote(
|
||||
(H256::from_low_u64_le(1), 1),
|
||||
&(H256::from_low_u64_le(1), 1),
|
||||
(Keyring::Dave.public(), Keyring::Dave.sign(b"I am committed"))
|
||||
));
|
||||
|
||||
assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1)));
|
||||
|
||||
assert!(rounds.add_vote(
|
||||
(H256::from_low_u64_le(1), 1),
|
||||
&(H256::from_low_u64_le(1), 1),
|
||||
(Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed"))
|
||||
));
|
||||
|
||||
assert!(!rounds.is_done(&(H256::from_low_u64_le(1), 1)));
|
||||
|
||||
assert!(rounds.add_vote(
|
||||
(H256::from_low_u64_le(1), 1),
|
||||
&(H256::from_low_u64_le(1), 1),
|
||||
(Keyring::Charlie.public(), Keyring::Charlie.sign(b"I am committed"))
|
||||
));
|
||||
|
||||
@@ -225,31 +225,31 @@ mod tests {
|
||||
|
||||
// round 1
|
||||
rounds.add_vote(
|
||||
(H256::from_low_u64_le(1), 1),
|
||||
&(H256::from_low_u64_le(1), 1),
|
||||
(Keyring::Alice.public(), Keyring::Alice.sign(b"I am committed")),
|
||||
);
|
||||
rounds.add_vote(
|
||||
(H256::from_low_u64_le(1), 1),
|
||||
&(H256::from_low_u64_le(1), 1),
|
||||
(Keyring::Bob.public(), Keyring::Bob.sign(b"I am committed")),
|
||||
);
|
||||
|
||||
// round 2
|
||||
rounds.add_vote(
|
||||
(H256::from_low_u64_le(2), 2),
|
||||
&(H256::from_low_u64_le(2), 2),
|
||||
(Keyring::Alice.public(), Keyring::Alice.sign(b"I am again committed")),
|
||||
);
|
||||
rounds.add_vote(
|
||||
(H256::from_low_u64_le(2), 2),
|
||||
&(H256::from_low_u64_le(2), 2),
|
||||
(Keyring::Bob.public(), Keyring::Bob.sign(b"I am again committed")),
|
||||
);
|
||||
|
||||
// round 3
|
||||
rounds.add_vote(
|
||||
(H256::from_low_u64_le(3), 3),
|
||||
&(H256::from_low_u64_le(3), 3),
|
||||
(Keyring::Alice.public(), Keyring::Alice.sign(b"I am still committed")),
|
||||
);
|
||||
rounds.add_vote(
|
||||
(H256::from_low_u64_le(3), 3),
|
||||
&(H256::from_low_u64_le(3), 3),
|
||||
(Keyring::Bob.public(), Keyring::Bob.sign(b"I am still committed")),
|
||||
);
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ use sp_runtime::{
|
||||
|
||||
use beefy_primitives::{
|
||||
crypto::{AuthorityId, Public, Signature},
|
||||
BeefyApi, Commitment, ConsensusLog, MmrRootHash, SignedCommitment, ValidatorSet,
|
||||
VersionedCommitment, VoteMessage, BEEFY_ENGINE_ID, GENESIS_AUTHORITY_SET_ID,
|
||||
known_payload_ids, BeefyApi, Commitment, ConsensusLog, MmrRootHash, Payload, SignedCommitment,
|
||||
ValidatorSet, VersionedCommitment, VoteMessage, BEEFY_ENGINE_ID, GENESIS_AUTHORITY_SET_ID,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -79,7 +79,7 @@ where
|
||||
/// Min delta in block numbers between two blocks, BEEFY should vote on
|
||||
min_block_delta: u32,
|
||||
metrics: Option<Metrics>,
|
||||
rounds: round::Rounds<MmrRootHash, NumberFor<B>>,
|
||||
rounds: round::Rounds<Payload, NumberFor<B>>,
|
||||
finality_notifications: FinalityNotifications<B>,
|
||||
/// Best block we received a GRANDPA notification for
|
||||
best_grandpa_block: NumberFor<B>,
|
||||
@@ -262,8 +262,9 @@ where
|
||||
return
|
||||
};
|
||||
|
||||
let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, mmr_root.encode());
|
||||
let commitment = Commitment {
|
||||
payload: mmr_root,
|
||||
payload,
|
||||
block_number: notification.header.number(),
|
||||
validator_set_id: self.rounds.validator_set_id(),
|
||||
};
|
||||
@@ -301,10 +302,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_vote(&mut self, round: (MmrRootHash, NumberFor<B>), vote: (Public, Signature)) {
|
||||
fn handle_vote(&mut self, round: (Payload, NumberFor<B>), vote: (Public, Signature)) {
|
||||
self.gossip_validator.note_round(round.1);
|
||||
|
||||
let vote_added = self.rounds.add_vote(round, vote);
|
||||
let vote_added = self.rounds.add_vote(&round, vote);
|
||||
|
||||
if vote_added && self.rounds.is_done(&round) {
|
||||
if let Some(signatures) = self.rounds.drop(&round) {
|
||||
@@ -352,7 +353,7 @@ where
|
||||
|notification| async move {
|
||||
debug!(target: "beefy", "🥩 Got vote message: {:?}", notification);
|
||||
|
||||
VoteMessage::<MmrRootHash, NumberFor<B>, Public, Signature>::decode(
|
||||
VoteMessage::<NumberFor<B>, Public, Signature>::decode(
|
||||
&mut ¬ification.message[..],
|
||||
)
|
||||
.ok()
|
||||
|
||||
@@ -18,8 +18,8 @@ sp-runtime = { version = "4.0.0-dev", path = "../runtime", default-features = fa
|
||||
sp-std = { version = "4.0.0-dev", path = "../std", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4.3"
|
||||
hex-literal = "0.3"
|
||||
|
||||
sp-keystore = { version = "0.10.0-dev", path = "../keystore" }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -15,10 +15,65 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use sp_std::{cmp, prelude::*};
|
||||
|
||||
use crate::{crypto::Signature, ValidatorSetId};
|
||||
|
||||
/// Id of different payloads in the [`Commitment`] data
|
||||
pub type BeefyPayloadId = [u8; 2];
|
||||
|
||||
/// Registry of all known [`BeefyPayloadId`].
|
||||
pub mod known_payload_ids {
|
||||
use crate::BeefyPayloadId;
|
||||
|
||||
/// A [`Payload`] identifier for Merkle Mountain Range root hash.
|
||||
///
|
||||
/// Encoded value should contain a [`beefy_primitives::MmrRootHash`] type (i.e. 32-bytes hash).
|
||||
pub const MMR_ROOT_ID: BeefyPayloadId = *b"mh";
|
||||
}
|
||||
|
||||
/// A BEEFY payload type allowing for future extensibility of adding additional kinds of payloads.
|
||||
///
|
||||
/// The idea is to store a vector of SCALE-encoded values with an extra identifier.
|
||||
/// Identifiers MUST be sorted by the [`BeefyPayloadId`] to allow efficient lookup of expected
|
||||
/// value. Duplicated identifiers are disallowed. It's okay for different implementations to only
|
||||
/// support a subset of possible values.
|
||||
#[derive(Decode, Encode, Debug, PartialEq, Eq, Clone, Ord, PartialOrd, Hash)]
|
||||
pub struct Payload(Vec<(BeefyPayloadId, Vec<u8>)>);
|
||||
|
||||
impl Payload {
|
||||
/// Construct a new payload given an initial vallue
|
||||
pub fn new(id: BeefyPayloadId, value: Vec<u8>) -> Self {
|
||||
Self(vec![(id, value)])
|
||||
}
|
||||
|
||||
/// Returns a raw payload under given `id`.
|
||||
///
|
||||
/// If the [`BeefyPayloadId`] is not found in the payload `None` is returned.
|
||||
pub fn get_raw(&self, id: &BeefyPayloadId) -> Option<&Vec<u8>> {
|
||||
let index = self.0.binary_search_by(|probe| probe.0.cmp(id)).ok()?;
|
||||
Some(&self.0[index].1)
|
||||
}
|
||||
|
||||
/// Returns a decoded payload value under given `id`.
|
||||
///
|
||||
/// In case the value is not there or it cannot be decoded does not match `None` is returned.
|
||||
pub fn get_decoded<T: Decode>(&self, id: &BeefyPayloadId) -> Option<T> {
|
||||
self.get_raw(id).and_then(|raw| T::decode(&mut &raw[..]).ok())
|
||||
}
|
||||
|
||||
/// Push a `Vec<u8>` with a given id into the payload vec.
|
||||
/// This method will internally sort the payload vec after every push.
|
||||
///
|
||||
/// Returns self to allow for daisy chaining.
|
||||
pub fn push_raw(mut self, id: BeefyPayloadId, value: Vec<u8>) -> Self {
|
||||
self.0.push((id, value));
|
||||
self.0.sort_by_key(|(id, _)| *id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A commitment signed by GRANDPA validators as part of BEEFY protocol.
|
||||
///
|
||||
/// The commitment contains a [payload](Commitment::payload) extracted from the finalized block at
|
||||
@@ -26,16 +81,17 @@ use crate::{crypto::Signature, ValidatorSetId};
|
||||
/// GRANDPA validators collect signatures on commitments and a stream of such signed commitments
|
||||
/// (see [SignedCommitment]) forms the BEEFY protocol.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)]
|
||||
pub struct Commitment<TBlockNumber, TPayload> {
|
||||
/// The payload being signed.
|
||||
pub struct Commitment<TBlockNumber> {
|
||||
/// A collection of payloads to be signed, see [`Payload`] for details.
|
||||
///
|
||||
/// This should be some form of cumulative representation of the chain (think MMR root hash).
|
||||
/// The payload should also contain some details that allow the light client to verify next
|
||||
/// validator set. The protocol does not enforce any particular format of this data,
|
||||
/// nor how often it should be present in commitments, however the light client has to be
|
||||
/// provided with full validator set whenever it performs the transition (i.e. importing first
|
||||
/// block with [validator_set_id](Commitment::validator_set_id) incremented).
|
||||
pub payload: TPayload,
|
||||
/// One of the payloads should be some form of cumulative representation of the chain (think
|
||||
/// MMR root hash). Additionally one of the payloads should also contain some details that
|
||||
/// allow the light client to verify next validator set. The protocol does not enforce any
|
||||
/// particular format of this data, nor how often it should be present in commitments, however
|
||||
/// the light client has to be provided with full validator set whenever it performs the
|
||||
/// transition (i.e. importing first block with
|
||||
/// [validator_set_id](Commitment::validator_set_id) incremented).
|
||||
pub payload: Payload,
|
||||
|
||||
/// Finalized block number this commitment is for.
|
||||
///
|
||||
@@ -57,20 +113,18 @@ pub struct Commitment<TBlockNumber, TPayload> {
|
||||
pub validator_set_id: ValidatorSetId,
|
||||
}
|
||||
|
||||
impl<TBlockNumber, TPayload> cmp::PartialOrd for Commitment<TBlockNumber, TPayload>
|
||||
impl<TBlockNumber> cmp::PartialOrd for Commitment<TBlockNumber>
|
||||
where
|
||||
TBlockNumber: cmp::Ord,
|
||||
TPayload: cmp::Eq,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<TBlockNumber, TPayload> cmp::Ord for Commitment<TBlockNumber, TPayload>
|
||||
impl<TBlockNumber> cmp::Ord for Commitment<TBlockNumber>
|
||||
where
|
||||
TBlockNumber: cmp::Ord,
|
||||
TPayload: cmp::Eq,
|
||||
{
|
||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||
self.validator_set_id
|
||||
@@ -81,9 +135,9 @@ where
|
||||
|
||||
/// A commitment with matching GRANDPA validators' signatures.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)]
|
||||
pub struct SignedCommitment<TBlockNumber, TPayload> {
|
||||
pub struct SignedCommitment<TBlockNumber> {
|
||||
/// The commitment signatures are collected for.
|
||||
pub commitment: Commitment<TBlockNumber, TPayload>,
|
||||
pub commitment: Commitment<TBlockNumber>,
|
||||
/// GRANDPA validators' signatures for the commitment.
|
||||
///
|
||||
/// The length of this `Vec` must match number of validators in the current set (see
|
||||
@@ -91,7 +145,7 @@ pub struct SignedCommitment<TBlockNumber, TPayload> {
|
||||
pub signatures: Vec<Option<Signature>>,
|
||||
}
|
||||
|
||||
impl<TBlockNumber, TPayload> SignedCommitment<TBlockNumber, TPayload> {
|
||||
impl<TBlockNumber> SignedCommitment<TBlockNumber> {
|
||||
/// Return the number of collected signatures.
|
||||
pub fn no_of_signatures(&self) -> usize {
|
||||
self.signatures.iter().filter(|x| x.is_some()).count()
|
||||
@@ -102,10 +156,10 @@ impl<TBlockNumber, TPayload> SignedCommitment<TBlockNumber, TPayload> {
|
||||
/// to the block justifications for the block for which the signed commitment
|
||||
/// has been generated.
|
||||
#[derive(Clone, Debug, PartialEq, codec::Encode, codec::Decode)]
|
||||
pub enum VersionedCommitment<N, P> {
|
||||
pub enum VersionedCommitment<N> {
|
||||
#[codec(index = 1)]
|
||||
/// Current active version
|
||||
V1(SignedCommitment<N, P>),
|
||||
V1(SignedCommitment<N>),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -119,9 +173,9 @@ mod tests {
|
||||
|
||||
use crate::{crypto, KEY_TYPE};
|
||||
|
||||
type TestCommitment = Commitment<u128, String>;
|
||||
type TestSignedCommitment = SignedCommitment<u128, String>;
|
||||
type TestVersionedCommitment = VersionedCommitment<u128, String>;
|
||||
type TestCommitment = Commitment<u128>;
|
||||
type TestSignedCommitment = SignedCommitment<u128>;
|
||||
type TestVersionedCommitment = VersionedCommitment<u128>;
|
||||
|
||||
// The mock signatures are equivalent to the ones produced by the BEEFY keystore
|
||||
fn mock_signatures() -> (crypto::Signature, crypto::Signature) {
|
||||
@@ -148,8 +202,9 @@ mod tests {
|
||||
#[test]
|
||||
fn commitment_encode_decode() {
|
||||
// given
|
||||
let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode());
|
||||
let commitment: TestCommitment =
|
||||
Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 };
|
||||
Commitment { payload, block_number: 5, validator_set_id: 0 };
|
||||
|
||||
// when
|
||||
let encoded = codec::Encode::encode(&commitment);
|
||||
@@ -160,7 +215,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
encoded,
|
||||
hex_literal::hex!(
|
||||
"3048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000"
|
||||
"046d68343048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -168,8 +223,9 @@ mod tests {
|
||||
#[test]
|
||||
fn signed_commitment_encode_decode() {
|
||||
// given
|
||||
let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode());
|
||||
let commitment: TestCommitment =
|
||||
Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 };
|
||||
Commitment { payload, block_number: 5, validator_set_id: 0 };
|
||||
|
||||
let sigs = mock_signatures();
|
||||
|
||||
@@ -187,10 +243,11 @@ mod tests {
|
||||
assert_eq!(
|
||||
encoded,
|
||||
hex_literal::hex!(
|
||||
"3048656c6c6f20576f726c64210500000000000000000000000000000000000000000000001000
|
||||
0001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e99a830e314d
|
||||
10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86cdd9aaacdc496577f3db8c55ef9e6fd48f2c5c05a
|
||||
2274707491635d8ba3df64f324575b7b2a34487bca2324b6a0046395a71681be3d0c2a00"
|
||||
"046d68343048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000
|
||||
10000001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321
|
||||
f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86cdd9aaa
|
||||
cdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bca2324b6a
|
||||
0046395a71681be3d0c2a00"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -198,8 +255,9 @@ mod tests {
|
||||
#[test]
|
||||
fn signed_commitment_count_signatures() {
|
||||
// given
|
||||
let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode());
|
||||
let commitment: TestCommitment =
|
||||
Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 };
|
||||
Commitment { payload, block_number: 5, validator_set_id: 0 };
|
||||
|
||||
let sigs = mock_signatures();
|
||||
|
||||
@@ -222,7 +280,8 @@ mod tests {
|
||||
block_number: u128,
|
||||
validator_set_id: crate::ValidatorSetId,
|
||||
) -> TestCommitment {
|
||||
Commitment { payload: "Hello World!".into(), block_number, validator_set_id }
|
||||
let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode());
|
||||
Commitment { payload, block_number, validator_set_id }
|
||||
}
|
||||
|
||||
// given
|
||||
@@ -241,8 +300,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn versioned_commitment_encode_decode() {
|
||||
let payload = Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".encode());
|
||||
let commitment: TestCommitment =
|
||||
Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 };
|
||||
Commitment { payload, block_number: 5, validator_set_id: 0 };
|
||||
|
||||
let sigs = mock_signatures();
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ mod commitment;
|
||||
pub mod mmr;
|
||||
pub mod witness;
|
||||
|
||||
pub use commitment::{Commitment, SignedCommitment, VersionedCommitment};
|
||||
pub use commitment::{
|
||||
known_payload_ids, BeefyPayloadId, Commitment, Payload, SignedCommitment, VersionedCommitment,
|
||||
};
|
||||
|
||||
use codec::{Codec, Decode, Encode};
|
||||
use scale_info::TypeInfo;
|
||||
@@ -118,9 +120,9 @@ pub enum ConsensusLog<AuthorityId: Codec> {
|
||||
/// A vote message is a direct vote created by a BEEFY node on every voting round
|
||||
/// and is gossiped to its peers.
|
||||
#[derive(Debug, Decode, Encode, TypeInfo)]
|
||||
pub struct VoteMessage<Hash, Number, Id, Signature> {
|
||||
pub struct VoteMessage<Number, Id, Signature> {
|
||||
/// Commit to information extracted from a finalized block
|
||||
pub commitment: Commitment<Number, Hash>,
|
||||
pub commitment: Commitment<Number>,
|
||||
/// Node authority id
|
||||
pub id: Id,
|
||||
/// Node signature
|
||||
|
||||
@@ -40,9 +40,9 @@ use crate::{
|
||||
/// Ethereum Mainnet), in a commit-reveal like scheme, where first we submit only the signed
|
||||
/// commitment witness and later on, the client picks only some signatures to verify at random.
|
||||
#[derive(Debug, PartialEq, Eq, codec::Encode, codec::Decode)]
|
||||
pub struct SignedCommitmentWitness<TBlockNumber, TPayload, TMerkleRoot> {
|
||||
pub struct SignedCommitmentWitness<TBlockNumber, TMerkleRoot> {
|
||||
/// The full content of the commitment.
|
||||
pub commitment: Commitment<TBlockNumber, TPayload>,
|
||||
pub commitment: Commitment<TBlockNumber>,
|
||||
|
||||
/// The bit vector of validators who signed the commitment.
|
||||
pub signed_by: Vec<bool>, // TODO [ToDr] Consider replacing with bitvec crate
|
||||
@@ -51,9 +51,7 @@ pub struct SignedCommitmentWitness<TBlockNumber, TPayload, TMerkleRoot> {
|
||||
pub signatures_merkle_root: TMerkleRoot,
|
||||
}
|
||||
|
||||
impl<TBlockNumber, TPayload, TMerkleRoot>
|
||||
SignedCommitmentWitness<TBlockNumber, TPayload, TMerkleRoot>
|
||||
{
|
||||
impl<TBlockNumber, TMerkleRoot> SignedCommitmentWitness<TBlockNumber, TMerkleRoot> {
|
||||
/// Convert [SignedCommitment] into [SignedCommitmentWitness].
|
||||
///
|
||||
/// This takes a [SignedCommitment], which contains full signatures
|
||||
@@ -63,7 +61,7 @@ impl<TBlockNumber, TPayload, TMerkleRoot>
|
||||
///
|
||||
/// Returns the full list of signatures along with the witness.
|
||||
pub fn from_signed<TMerkelize>(
|
||||
signed: SignedCommitment<TBlockNumber, TPayload>,
|
||||
signed: SignedCommitment<TBlockNumber>,
|
||||
merkelize: TMerkelize,
|
||||
) -> (Self, Vec<Option<Signature>>)
|
||||
where
|
||||
@@ -86,12 +84,11 @@ mod tests {
|
||||
use super::*;
|
||||
use codec::Decode;
|
||||
|
||||
use crate::{crypto, KEY_TYPE};
|
||||
use crate::{crypto, known_payload_ids, Payload, KEY_TYPE};
|
||||
|
||||
type TestCommitment = Commitment<u128, String>;
|
||||
type TestSignedCommitment = SignedCommitment<u128, String>;
|
||||
type TestSignedCommitmentWitness =
|
||||
SignedCommitmentWitness<u128, String, Vec<Option<Signature>>>;
|
||||
type TestCommitment = Commitment<u128>;
|
||||
type TestSignedCommitment = SignedCommitment<u128>;
|
||||
type TestSignedCommitmentWitness = SignedCommitmentWitness<u128, Vec<Option<Signature>>>;
|
||||
|
||||
// The mock signatures are equivalent to the ones produced by the BEEFY keystore
|
||||
fn mock_signatures() -> (crypto::Signature, crypto::Signature) {
|
||||
@@ -116,8 +113,10 @@ mod tests {
|
||||
}
|
||||
|
||||
fn signed_commitment() -> TestSignedCommitment {
|
||||
let payload =
|
||||
Payload::new(known_payload_ids::MMR_ROOT_ID, "Hello World!".as_bytes().to_vec());
|
||||
let commitment: TestCommitment =
|
||||
Commitment { payload: "Hello World!".into(), block_number: 5, validator_set_id: 0 };
|
||||
Commitment { payload, block_number: 5, validator_set_id: 0 };
|
||||
|
||||
let sigs = mock_signatures();
|
||||
|
||||
@@ -152,10 +151,11 @@ mod tests {
|
||||
assert_eq!(
|
||||
encoded,
|
||||
hex_literal::hex!(
|
||||
"3048656c6c6f20576f726c64210500000000000000000000000000000000000000000000001000
|
||||
00010110000001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c746cc321f2319a5e9
|
||||
9a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86cdd9aaacdc496577f3db8c55ef9e6fd
|
||||
48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bca2324b6a0046395a71681be3d0c2a00"
|
||||
"046d683048656c6c6f20576f726c642105000000000000000000000000000000000000000000000010
|
||||
0000010110000001558455ad81279df0795cc985580e4fb75d72d948d1107b2ac80a09abed4da8480c
|
||||
746cc321f2319a5e99a830e314d10dd3cd68ce3dc0c33c86e99bcb7816f9ba01012d6e1f8105c337a86
|
||||
cdd9aaacdc496577f3db8c55ef9e6fd48f2c5c05a2274707491635d8ba3df64f324575b7b2a34487bc
|
||||
a2324b6a0046395a71681be3d0c2a00"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user