github.com/okex/exchain@v1.8.0/libs/tendermint/lite/helpers.go (about) 1 package lite 2 3 import ( 4 "github.com/okex/exchain/libs/tendermint/crypto" 5 "github.com/okex/exchain/libs/tendermint/crypto/ed25519" 6 "github.com/okex/exchain/libs/tendermint/crypto/secp256k1" 7 8 "github.com/okex/exchain/libs/tendermint/types" 9 tmtime "github.com/okex/exchain/libs/tendermint/types/time" 10 ) 11 12 // PrivKeys is a helper type for testing. 13 // 14 // It lets us simulate signing with many keys. The main use case is to create 15 // a set, and call GenSignedHeader to get properly signed header for testing. 16 // 17 // You can set different weights of validators each time you call ToValidators, 18 // and can optionally extend the validator set later with Extend. 19 type privKeys []crypto.PrivKey 20 21 // genPrivKeys produces an array of private keys to generate commits. 22 func genPrivKeys(n int) privKeys { 23 res := make(privKeys, n) 24 for i := range res { 25 res[i] = ed25519.GenPrivKey() 26 } 27 return res 28 } 29 30 // Change replaces the key at index i. 31 func (pkz privKeys) Change(i int) privKeys { 32 res := make(privKeys, len(pkz)) 33 copy(res, pkz) 34 res[i] = ed25519.GenPrivKey() 35 return res 36 } 37 38 // Extend adds n more keys (to remove, just take a slice). 39 func (pkz privKeys) Extend(n int) privKeys { 40 extra := genPrivKeys(n) 41 return append(pkz, extra...) 42 } 43 44 // GenSecpPrivKeys produces an array of secp256k1 private keys to generate commits. 45 func genSecpPrivKeys(n int) privKeys { 46 res := make(privKeys, n) 47 for i := range res { 48 res[i] = secp256k1.GenPrivKey() 49 } 50 return res 51 } 52 53 // ExtendSecp adds n more secp256k1 keys (to remove, just take a slice). 54 func (pkz privKeys) ExtendSecp(n int) privKeys { 55 extra := genSecpPrivKeys(n) 56 return append(pkz, extra...) 57 } 58 59 // ToValidators produces a valset from the set of keys. 60 // The first key has weight `init` and it increases by `inc` every step 61 // so we can have all the same weight, or a simple linear distribution 62 // (should be enough for testing). 63 func (pkz privKeys) ToValidators(init, inc int64) *types.ValidatorSet { 64 res := make([]*types.Validator, len(pkz)) 65 for i, k := range pkz { 66 res[i] = types.NewValidator(k.PubKey(), init+int64(i)*inc) 67 } 68 return types.NewValidatorSet(res) 69 } 70 71 // signHeader properly signs the header with all keys from first to last exclusive. 72 func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Commit { 73 commitSigs := make([]types.CommitSig, len(pkz)) 74 for i := 0; i < len(pkz); i++ { 75 commitSigs[i] = types.NewCommitSigAbsent() 76 } 77 78 // We need this list to keep the ordering. 79 vset := pkz.ToValidators(1, 0) 80 81 blockID := types.BlockID{ 82 Hash: header.Hash(), 83 PartsHeader: types.PartSetHeader{Total: 1, Hash: crypto.CRandBytes(32)}, 84 } 85 86 // Fill in the votes we want. 87 for i := first; i < last && i < len(pkz); i++ { 88 vote := makeVote(header, vset, pkz[i], blockID) 89 commitSigs[vote.ValidatorIndex] = vote.CommitSig() 90 } 91 92 return types.NewCommit(header.Height, 1, blockID, commitSigs) 93 } 94 95 func makeVote(header *types.Header, valset *types.ValidatorSet, key crypto.PrivKey, blockID types.BlockID) *types.Vote { 96 addr := key.PubKey().Address() 97 idx, _ := valset.GetByAddress(addr) 98 vote := &types.Vote{ 99 ValidatorAddress: addr, 100 ValidatorIndex: idx, 101 Height: header.Height, 102 Round: 1, 103 Timestamp: tmtime.Now(), 104 Type: types.PrecommitType, 105 BlockID: blockID, 106 } 107 // Sign it 108 signBytes := vote.SignBytes(header.ChainID) 109 // TODO Consider reworking makeVote API to return an error 110 sig, err := key.Sign(signBytes) 111 if err != nil { 112 panic(err) 113 } 114 vote.Signature = sig 115 116 return vote 117 } 118 119 func genHeader(chainID string, height int64, txs types.Txs, 120 valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte) *types.Header { 121 122 return &types.Header{ 123 ChainID: chainID, 124 Height: height, 125 Time: tmtime.Now(), 126 // LastBlockID 127 // LastCommitHash 128 ValidatorsHash: valset.Hash(height), 129 NextValidatorsHash: nextValset.Hash(height + 1), 130 DataHash: txs.Hash(height), 131 AppHash: appHash, 132 ConsensusHash: consHash, 133 LastResultsHash: resHash, 134 } 135 } 136 137 // GenSignedHeader calls genHeader and signHeader and combines them into a SignedHeader. 138 func (pkz privKeys) GenSignedHeader(chainID string, height int64, txs types.Txs, 139 valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, first, last int) types.SignedHeader { 140 141 header := genHeader(chainID, height, txs, valset, nextValset, appHash, consHash, resHash) 142 check := types.SignedHeader{ 143 Header: header, 144 Commit: pkz.signHeader(header, first, last), 145 } 146 return check 147 } 148 149 // GenFullCommit calls genHeader and signHeader and combines them into a FullCommit. 150 func (pkz privKeys) GenFullCommit(chainID string, height int64, txs types.Txs, 151 valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, first, last int) FullCommit { 152 153 header := genHeader(chainID, height, txs, valset, nextValset, appHash, consHash, resHash) 154 commit := types.SignedHeader{ 155 Header: header, 156 Commit: pkz.signHeader(header, first, last), 157 } 158 return NewFullCommit(commit, valset, nextValset) 159 }