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