github.com/soomindae/tendermint@v0.0.5-0.20210528140126-84a0c70c8162/light/helpers_test.go (about) 1 package light_test 2 3 import ( 4 "time" 5 6 "github.com/soomindae/tendermint/crypto" 7 "github.com/soomindae/tendermint/crypto/ed25519" 8 "github.com/soomindae/tendermint/crypto/tmhash" 9 tmproto "github.com/soomindae/tendermint/proto/tendermint/types" 10 tmversion "github.com/soomindae/tendermint/proto/tendermint/version" 11 "github.com/soomindae/tendermint/types" 12 tmtime "github.com/soomindae/tendermint/types/time" 13 "github.com/soomindae/tendermint/version" 14 ) 15 16 // privKeys is a helper type for testing. 17 // 18 // It lets us simulate signing with many keys. The main use case is to create 19 // a set, and call GenSignedHeader to get properly signed header for testing. 20 // 21 // You can set different weights of validators each time you call ToValidators, 22 // and can optionally extend the validator set later with Extend. 23 type privKeys []crypto.PrivKey 24 25 // genPrivKeys produces an array of private keys to generate commits. 26 func genPrivKeys(n int) privKeys { 27 res := make(privKeys, n) 28 for i := range res { 29 res[i] = ed25519.GenPrivKey() 30 } 31 return res 32 } 33 34 // // Change replaces the key at index i. 35 // func (pkz privKeys) Change(i int) privKeys { 36 // res := make(privKeys, len(pkz)) 37 // copy(res, pkz) 38 // res[i] = ed25519.GenPrivKey() 39 // return res 40 // } 41 42 // Extend adds n more keys (to remove, just take a slice). 43 func (pkz privKeys) Extend(n int) privKeys { 44 extra := genPrivKeys(n) 45 return append(pkz, extra...) 46 } 47 48 // // GenSecpPrivKeys produces an array of secp256k1 private keys to generate commits. 49 // func GenSecpPrivKeys(n int) privKeys { 50 // res := make(privKeys, n) 51 // for i := range res { 52 // res[i] = secp256k1.GenPrivKey() 53 // } 54 // return res 55 // } 56 57 // // ExtendSecp adds n more secp256k1 keys (to remove, just take a slice). 58 // func (pkz privKeys) ExtendSecp(n int) privKeys { 59 // extra := GenSecpPrivKeys(n) 60 // return append(pkz, extra...) 61 // } 62 63 // ToValidators produces a valset from the set of keys. 64 // The first key has weight `init` and it increases by `inc` every step 65 // so we can have all the same weight, or a simple linear distribution 66 // (should be enough for testing). 67 func (pkz privKeys) ToValidators(init, inc int64) *types.ValidatorSet { 68 res := make([]*types.Validator, len(pkz)) 69 for i, k := range pkz { 70 res[i] = types.NewValidator(k.PubKey(), init+int64(i)*inc) 71 } 72 return types.NewValidatorSet(res) 73 } 74 75 // signHeader properly signs the header with all keys from first to last exclusive. 76 func (pkz privKeys) signHeader(header *types.Header, valSet *types.ValidatorSet, first, last int) *types.Commit { 77 commitSigs := make([]types.CommitSig, len(pkz)) 78 for i := 0; i < len(pkz); i++ { 79 commitSigs[i] = types.NewCommitSigAbsent() 80 } 81 82 blockID := types.BlockID{ 83 Hash: header.Hash(), 84 PartSetHeader: types.PartSetHeader{Total: 1, Hash: crypto.CRandBytes(32)}, 85 } 86 87 // Fill in the votes we want. 88 for i := first; i < last && i < len(pkz); i++ { 89 vote := makeVote(header, valSet, pkz[i], blockID) 90 commitSigs[vote.ValidatorIndex] = vote.CommitSig() 91 } 92 93 return types.NewCommit(header.Height, 1, blockID, commitSigs) 94 } 95 96 func makeVote(header *types.Header, valset *types.ValidatorSet, 97 key crypto.PrivKey, blockID types.BlockID) *types.Vote { 98 99 addr := key.PubKey().Address() 100 idx, _ := valset.GetByAddress(addr) 101 vote := &types.Vote{ 102 ValidatorAddress: addr, 103 ValidatorIndex: idx, 104 Height: header.Height, 105 Round: 1, 106 Timestamp: tmtime.Now(), 107 Type: tmproto.PrecommitType, 108 BlockID: blockID, 109 } 110 111 v := vote.ToProto() 112 // Sign it 113 signBytes := types.VoteSignBytes(header.ChainID, v) 114 sig, err := key.Sign(signBytes) 115 if err != nil { 116 panic(err) 117 } 118 119 vote.Signature = sig 120 121 return vote 122 } 123 124 func genHeader(chainID string, height int64, bTime time.Time, txs types.Txs, 125 valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte) *types.Header { 126 127 return &types.Header{ 128 Version: tmversion.Consensus{Block: version.BlockProtocol, App: 0}, 129 ChainID: chainID, 130 Height: height, 131 Time: bTime, 132 // LastBlockID 133 // LastCommitHash 134 ValidatorsHash: valset.Hash(), 135 NextValidatorsHash: nextValset.Hash(), 136 DataHash: txs.Hash(), 137 AppHash: appHash, 138 ConsensusHash: consHash, 139 LastResultsHash: resHash, 140 ProposerAddress: valset.Validators[0].Address, 141 } 142 } 143 144 // GenSignedHeader calls genHeader and signHeader and combines them into a SignedHeader. 145 func (pkz privKeys) GenSignedHeader(chainID string, height int64, bTime time.Time, txs types.Txs, 146 valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, first, last int) *types.SignedHeader { 147 148 header := genHeader(chainID, height, bTime, txs, valset, nextValset, appHash, consHash, resHash) 149 return &types.SignedHeader{ 150 Header: header, 151 Commit: pkz.signHeader(header, valset, first, last), 152 } 153 } 154 155 // GenSignedHeaderLastBlockID calls genHeader and signHeader and combines them into a SignedHeader. 156 func (pkz privKeys) GenSignedHeaderLastBlockID(chainID string, height int64, bTime time.Time, txs types.Txs, 157 valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, first, last int, 158 lastBlockID types.BlockID) *types.SignedHeader { 159 160 header := genHeader(chainID, height, bTime, txs, valset, nextValset, appHash, consHash, resHash) 161 header.LastBlockID = lastBlockID 162 return &types.SignedHeader{ 163 Header: header, 164 Commit: pkz.signHeader(header, valset, first, last), 165 } 166 } 167 168 func (pkz privKeys) ChangeKeys(delta int) privKeys { 169 newKeys := pkz[delta:] 170 return newKeys.Extend(delta) 171 } 172 173 // Generates the header and validator set to create a full entire mock node with blocks to height ( 174 // blockSize) and with variation in validator sets. BlockIntervals are in per minute. 175 // NOTE: Expected to have a large validator set size ~ 100 validators. 176 func genMockNodeWithKeys( 177 chainID string, 178 blockSize int64, 179 valSize int, 180 valVariation float32, 181 bTime time.Time) ( 182 map[int64]*types.SignedHeader, 183 map[int64]*types.ValidatorSet, 184 map[int64]privKeys) { 185 186 var ( 187 headers = make(map[int64]*types.SignedHeader, blockSize) 188 valset = make(map[int64]*types.ValidatorSet, blockSize+1) 189 keymap = make(map[int64]privKeys, blockSize+1) 190 keys = genPrivKeys(valSize) 191 totalVariation = valVariation 192 valVariationInt int 193 newKeys privKeys 194 ) 195 196 valVariationInt = int(totalVariation) 197 totalVariation = -float32(valVariationInt) 198 newKeys = keys.ChangeKeys(valVariationInt) 199 keymap[1] = keys 200 keymap[2] = newKeys 201 202 // genesis header and vals 203 lastHeader := keys.GenSignedHeader(chainID, 1, bTime.Add(1*time.Minute), nil, 204 keys.ToValidators(2, 0), newKeys.ToValidators(2, 0), hash("app_hash"), hash("cons_hash"), 205 hash("results_hash"), 0, len(keys)) 206 currentHeader := lastHeader 207 headers[1] = currentHeader 208 valset[1] = keys.ToValidators(2, 0) 209 keys = newKeys 210 211 for height := int64(2); height <= blockSize; height++ { 212 totalVariation += valVariation 213 valVariationInt = int(totalVariation) 214 totalVariation = -float32(valVariationInt) 215 newKeys = keys.ChangeKeys(valVariationInt) 216 currentHeader = keys.GenSignedHeaderLastBlockID(chainID, height, bTime.Add(time.Duration(height)*time.Minute), 217 nil, 218 keys.ToValidators(2, 0), newKeys.ToValidators(2, 0), hash("app_hash"), hash("cons_hash"), 219 hash("results_hash"), 0, len(keys), types.BlockID{Hash: lastHeader.Hash()}) 220 headers[height] = currentHeader 221 valset[height] = keys.ToValidators(2, 0) 222 lastHeader = currentHeader 223 keys = newKeys 224 keymap[height+1] = keys 225 } 226 227 return headers, valset, keymap 228 } 229 230 func genMockNode( 231 chainID string, 232 blockSize int64, 233 valSize int, 234 valVariation float32, 235 bTime time.Time) ( 236 string, 237 map[int64]*types.SignedHeader, 238 map[int64]*types.ValidatorSet) { 239 headers, valset, _ := genMockNodeWithKeys(chainID, blockSize, valSize, valVariation, bTime) 240 return chainID, headers, valset 241 } 242 243 func hash(s string) []byte { 244 return tmhash.Sum([]byte(s)) 245 }