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:
Seun Lanlege
2021-12-01 12:45:36 +01:00
committed by GitHub
parent db37fb04e8
commit a18749d315
9 changed files with 152 additions and 99 deletions
+1
View File
@@ -535,6 +535,7 @@ dependencies = [
name = "beefy-primitives"
version = "4.0.0-dev"
dependencies = [
"hex",
"hex-literal",
"parity-scale-codec",
"scale-info",
+11 -21
View File
@@ -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);
+1 -2
View File
@@ -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>>;
+18 -18
View File
@@ -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")),
);
+8 -7
View File
@@ -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 &notification.message[..],
)
.ok()
+1 -1
View File
@@ -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]
+91 -31
View File
@@ -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();
+5 -3
View File
@@ -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
+16 -16
View File
@@ -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"
)
);
}