@@ -1539,6 +1539,32 @@ async fn join_2<T: Future, U: Future>(
15391539 futures:: join!( t, u)
15401540}
15411541
1542+ // The created RewardedSignatures should contain bit vectors for each of the block for which
1543+ // signatures are being cited. If we are eligible to cite 3 blocks, RewardsSignature will contain an
1544+ // at-most 3 vectors of bit vectors (Vec<Vec<u8>>). With `signature_rewards_max_delay = 3` The logic
1545+ // is - "we can cite signatures for the blocks parent, parents parent and parents parent parent".
1546+ // If we are close to genesis, the outer vector will obviously not have 3 entries.
1547+ // (At height 0 there is no parent, at height 1 there is no grandparent etc.)
1548+ // The `rewarded_signatures` vector will look something like:
1549+ // [[255, 64],[128, 0],[0, 0]]
1550+ // Entries in the outer vec are interpreted as:
1551+ // - on index 0 - the last finalized block
1552+ // - on index 1 - the penultimate finalized block
1553+ // - on index 2 - the penpenultimate finalized block
1554+ // There are at most `signature_rewards_max_delay` entries in this vector. if we are "close" to
1555+ // genesis there can be less (at height 0 there is no history, so there will be no cited blocks, at
1556+ // height 1 we can only cite signatures from one block etc.) Each entry in this vector is also a
1557+ // vector of u8 numbers. To interpret them we need to realize that if we concatenate all the bytes
1558+ // of the numbers, the nth bit will say that the nth validators signature was either cited (if the
1559+ // bit is 1) or not (if the bit is 0). To figure out which validator is on position n, we need to
1560+ // take all the validators relevant to the era of the particular block, fetch their public keys and
1561+ // sort them ascending. In the quoted example we see that: For the parent on the proposed block we
1562+ // cite signatures of validators on position 0, 1, 2, 3, 4, 5, 6, 7 and 9 For the grandparent on
1563+ // the proposed block we cite signatures of validators on position 0 For the grandgrandparent on
1564+ // the proposed block we cite no signatures Please note that due to using u8 as the "packing"
1565+ // mechanism it is possible that the byte vector will have more bits than there are validators - we
1566+ // round it up to 8 (ceiling(number_of_valuidators/8)), the remaining bits are only used as padding
1567+ // to full bytes.
15421568fn create_rewarded_signatures (
15431569 maybe_past_blocks_with_metadata : & [ Option < BlockWithMetadata > ] ,
15441570 validator_matrix : ValidatorMatrix ,
@@ -1595,3 +1621,136 @@ fn create_rewarded_signatures(
15951621
15961622 rewarded_signatures
15971623}
1624+
1625+ #[ cfg( test) ]
1626+ mod tests {
1627+ use std:: collections:: { BTreeMap , BTreeSet } ;
1628+
1629+ use crate :: {
1630+ consensus:: {
1631+ era_supervisor:: create_rewarded_signatures,
1632+ tests:: utils:: { ALICE_PUBLIC_KEY , ALICE_SECRET_KEY , BOB_PUBLIC_KEY , CAROL_PUBLIC_KEY } ,
1633+ BlockContext , ClContext ,
1634+ } ,
1635+ types:: { BlockWithMetadata , ValidatorMatrix } ,
1636+ } ;
1637+ use casper_types:: {
1638+ bytesrepr:: { Bytes , ToBytes } ,
1639+ testing:: TestRng ,
1640+ Block , BlockHash , BlockSignatures , BlockSignaturesV2 , BlockV2 , Digest , EraId ,
1641+ ProtocolVersion , PublicKey , RewardedSignatures , Signature , SingleBlockRewardedSignatures ,
1642+ Timestamp , U512 ,
1643+ } ;
1644+
1645+ #[ test]
1646+ fn should_set_first_bit_if_earliest_key_cited ( ) {
1647+ // The first bit in the bit list should be set to 1 if the "lowest" (in the sense of public
1648+ // key comaparison) public key signature was cited.
1649+ let mut rng = TestRng :: new ( ) ;
1650+
1651+ let mut bs_v2 = BlockSignaturesV2 :: random ( & mut rng) ;
1652+ bs_v2. insert_signature (
1653+ ALICE_PUBLIC_KEY . clone ( ) ,
1654+ Signature :: ed25519 ( [ 44 ; Signature :: ED25519_LENGTH ] ) . unwrap ( ) ,
1655+ ) ;
1656+ let signatures = build_rewarded_signatures_without_historical_blocks ( & mut rng, bs_v2) ;
1657+ assert_eq ! (
1658+ signatures. to_bytes( ) . unwrap( ) ,
1659+ vec![ Bytes :: from( vec![ 128_u8 ] ) ] . to_bytes( ) . unwrap( )
1660+ ) ;
1661+ }
1662+
1663+ #[ test]
1664+ fn should_set_third_bit_if_the_first_validator_signature_cited ( ) {
1665+ // Given there are three validators, if the first (by public key copmparison) validator
1666+ // signature was cited - the third bit should be set to 1
1667+ let mut rng = TestRng :: new ( ) ;
1668+
1669+ let mut bs_v2 = BlockSignaturesV2 :: random ( & mut rng) ;
1670+ bs_v2. insert_signature (
1671+ BOB_PUBLIC_KEY . clone ( ) ,
1672+ Signature :: ed25519 ( [ 44 ; Signature :: ED25519_LENGTH ] ) . unwrap ( ) ,
1673+ ) ;
1674+ let signatures = build_rewarded_signatures_without_historical_blocks ( & mut rng, bs_v2) ;
1675+ assert_eq ! (
1676+ signatures. to_bytes( ) . unwrap( ) ,
1677+ vec![ Bytes :: from( vec![ 32_u8 ] ) ] . to_bytes( ) . unwrap( )
1678+ ) ;
1679+ }
1680+
1681+ #[ test]
1682+ fn should_set_second_bit_if_the_second_validator_signature_cited ( ) {
1683+ // Given there are three validators, if the second (by public key copmparison) validator
1684+ // signature was cited - the second bit should be set to 1
1685+ let mut rng = TestRng :: new ( ) ;
1686+
1687+ let mut bs_v2 = BlockSignaturesV2 :: random ( & mut rng) ;
1688+ bs_v2. insert_signature (
1689+ CAROL_PUBLIC_KEY . clone ( ) ,
1690+ Signature :: ed25519 ( [ 44 ; Signature :: ED25519_LENGTH ] ) . unwrap ( ) ,
1691+ ) ;
1692+ let signatures = build_rewarded_signatures_without_historical_blocks ( & mut rng, bs_v2) ;
1693+ assert_eq ! (
1694+ signatures. to_bytes( ) . unwrap( ) ,
1695+ vec![ Bytes :: from( vec![ 64_u8 ] ) ] . to_bytes( ) . unwrap( )
1696+ ) ;
1697+ }
1698+
1699+ fn build_rewarded_signatures_without_historical_blocks (
1700+ rng : & mut TestRng ,
1701+ bs_v2 : BlockSignaturesV2 ,
1702+ ) -> RewardedSignatures {
1703+ assert ! ( * BOB_PUBLIC_KEY > * CAROL_PUBLIC_KEY && * CAROL_PUBLIC_KEY > * ALICE_PUBLIC_KEY ) ;
1704+ let signatures_1 = BTreeSet :: new ( ) ;
1705+ let mut validator_public_keys: BTreeMap < PublicKey , U512 > = BTreeMap :: new ( ) ;
1706+ // Making sure that Alice, Bob and Carols keys by stake have different ordering than
1707+ // by PublicKey
1708+ validator_public_keys. insert (
1709+ ALICE_PUBLIC_KEY . clone ( ) ,
1710+ U512 :: MAX . saturating_sub ( 100 . into ( ) ) ,
1711+ ) ;
1712+ validator_public_keys. insert ( BOB_PUBLIC_KEY . clone ( ) , 1_u64 . into ( ) ) ;
1713+ validator_public_keys. insert ( CAROL_PUBLIC_KEY . clone ( ) , U512 :: MAX ) ;
1714+
1715+ let past_rewarded_signatures =
1716+ RewardedSignatures :: new ( vec ! [ SingleBlockRewardedSignatures :: from_validator_set(
1717+ & signatures_1,
1718+ validator_public_keys. keys( ) ,
1719+ ) ] ) ;
1720+
1721+ let block_v2 = BlockV2 :: new (
1722+ BlockHash :: random ( rng) ,
1723+ Digest :: random ( rng) ,
1724+ Digest :: random ( rng) ,
1725+ false ,
1726+ None ,
1727+ Timestamp :: now ( ) ,
1728+ EraId :: new ( 1 ) ,
1729+ 1010 ,
1730+ ProtocolVersion :: V2_0_0 ,
1731+ PublicKey :: random ( rng) ,
1732+ BTreeMap :: new ( ) ,
1733+ past_rewarded_signatures,
1734+ 1 ,
1735+ None ,
1736+ ) ;
1737+ let block = Block :: V2 ( block_v2) ;
1738+
1739+ let block_1 = BlockWithMetadata {
1740+ block,
1741+ block_signatures : BlockSignatures :: V2 ( bs_v2) ,
1742+ } ;
1743+ let maybe_past_blocks_with_metadata = vec ! [ Some ( block_1) ] ;
1744+ let mut validator_matrix = ValidatorMatrix :: new_with_validator ( ALICE_SECRET_KEY . clone ( ) ) ;
1745+ validator_matrix. register_validator_weights ( EraId :: new ( 1 ) , validator_public_keys) ;
1746+ let timestamp = Timestamp :: now ( ) ;
1747+ let ancestor_values = vec ! [ ] ;
1748+ let block_context = BlockContext :: < ClContext > :: new ( timestamp, ancestor_values) ;
1749+ create_rewarded_signatures (
1750+ & maybe_past_blocks_with_metadata,
1751+ validator_matrix,
1752+ & block_context,
1753+ 1 ,
1754+ )
1755+ }
1756+ }
0 commit comments