From 5fb10aea2c2702a21ac66de6d5ad43b11dad130f Mon Sep 17 00:00:00 2001 From: zemyblue Date: Thu, 2 Apr 2020 17:03:08 +0900 Subject: [PATCH 1/5] * Add `LastProofHash` for genesis seed of first block in the `state.State`. * Add hash function in `GenesisDoc` * --- state/execution.go | 7 +++++++ state/state.go | 23 +++++++---------------- state/state_test.go | 3 +++ types/genesis.go | 5 +++++ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/state/execution.go b/state/execution.go index 5da00bcf6..8a6016fa6 100644 --- a/state/execution.go +++ b/state/execution.go @@ -427,6 +427,12 @@ func updateState( // TODO: allow app to upgrade version nextVersion := state.Version + // get proof hash from vrf proof + proofHash, err := vrf.ProofToHash(header.Proof.Bytes()) + if err != nil { + return state, fmt.Errorf("error get proof of hash: %v", err) + } + // NOTE: the AppHash has not been populated. // It will be filled on state.Save. return State{ @@ -436,6 +442,7 @@ func updateState( LastBlockID: blockID, LastBlockTime: header.Time, LastProof: header.Proof.Bytes(), + LastProofHash: proofHash, NextValidators: nValSet, Validators: state.NextValidators.Copy(), LastValidators: state.Validators.Copy(), diff --git a/state/state.go b/state/state.go index 3dd03120a..f10a13bc4 100644 --- a/state/state.go +++ b/state/state.go @@ -63,7 +63,8 @@ type State struct { LastBlockTime time.Time // vrf proof - LastProof vrf.Proof + LastProof vrf.Proof + LastProofHash []byte // LastValidators is used to validate block.LastCommit. // Validators are persisted to the database separately every time they change, @@ -89,23 +90,11 @@ type State struct { } func (state State) MakeHashMessage(round int) ([]byte, error) { - var seed []byte - - if len(state.LastProof) == 0 { - // TODO: This code is temporary. When genesis seed is prepared, use that code. - seed = []byte("LINE Blockchain VRF Algorithm's first seed") - } else { - output, err := vrf.ProofToHash(state.LastProof) - if err != nil { - return nil, err - } - seed = output - } b := make([]byte, 16) binary.LittleEndian.PutUint64(b, uint64(state.LastBlockHeight)) binary.LittleEndian.PutUint64(b[8:], uint64(round)) hash := tmhash.New() - hash.Write(seed) + hash.Write(state.LastProofHash) return hash.Sum(b), nil } @@ -119,7 +108,8 @@ func (state State) Copy() State { LastBlockID: state.LastBlockID, LastBlockTime: state.LastBlockTime, - LastProof: state.LastProof, + LastProof: state.LastProof, + LastProofHash: state.LastProofHash, NextValidators: state.NextValidators.Copy(), Validators: state.Validators.Copy(), @@ -272,7 +262,8 @@ func MakeGenesisState(genDoc *types.GenesisDoc) (State, error) { LastBlockTime: genDoc.GenesisTime, // genesis block has no last proof - LastProof: nil, + LastProof: nil, + LastProofHash: genDoc.Hash(), NextValidators: nextValidatorSet, Validators: validatorSet, diff --git a/state/state_test.go b/state/state_test.go index 25f916ee2..5484da6d4 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -3,6 +3,7 @@ package state_test import ( "bytes" "fmt" + "github.com/tendermint/tendermint/crypto/vrf" "math" "math/big" "os" @@ -1028,6 +1029,8 @@ func TestState_MakeHashMessage(t *testing.T) { privVal := makePrivVal() state.LastProof, _ = privVal.GenerateVRFProof(message1) + output, _ := vrf.ProofToHash(state.LastProof) + state.LastProofHash = output message3, err := state.MakeHashMessage(0) require.NoError(t, err) require.False(t, bytes.Equal(message1, message3)) diff --git a/types/genesis.go b/types/genesis.go index 73a7847d8..7ca328c9a 100644 --- a/types/genesis.go +++ b/types/genesis.go @@ -98,6 +98,11 @@ func (genDoc *GenesisDoc) ValidateAndComplete() error { return nil } +// Hash returns the hash of the GenesisDoc +func (genDoc *GenesisDoc) Hash() []byte { + return cdcEncode(genDoc) +} + //------------------------------------------------------------ // Make genesis state from file From 4a07bfce3e56a359e359c06d50a74904af821ed2 Mon Sep 17 00:00:00 2001 From: zemyblue Date: Thu, 2 Apr 2020 17:40:29 +0900 Subject: [PATCH 2/5] * Remove `LastProof` of state. --- state/execution.go | 1 - state/state.go | 5 +---- state/state_test.go | 4 ++-- state/validation.go | 4 ++-- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/state/execution.go b/state/execution.go index 8a6016fa6..170beaa7f 100644 --- a/state/execution.go +++ b/state/execution.go @@ -441,7 +441,6 @@ func updateState( LastBlockHeight: header.Height, LastBlockID: blockID, LastBlockTime: header.Time, - LastProof: header.Proof.Bytes(), LastProofHash: proofHash, NextValidators: nValSet, Validators: state.NextValidators.Copy(), diff --git a/state/state.go b/state/state.go index f10a13bc4..3eb3c16b1 100644 --- a/state/state.go +++ b/state/state.go @@ -63,7 +63,6 @@ type State struct { LastBlockTime time.Time // vrf proof - LastProof vrf.Proof LastProofHash []byte // LastValidators is used to validate block.LastCommit. @@ -108,7 +107,6 @@ func (state State) Copy() State { LastBlockID: state.LastBlockID, LastBlockTime: state.LastBlockTime, - LastProof: state.LastProof, LastProofHash: state.LastProofHash, NextValidators: state.NextValidators.Copy(), @@ -261,8 +259,7 @@ func MakeGenesisState(genDoc *types.GenesisDoc) (State, error) { LastBlockID: types.BlockID{}, LastBlockTime: genDoc.GenesisTime, - // genesis block has no last proof - LastProof: nil, + // genesis block use the hash of GenesisDoc instead for the `LastProofHash` LastProofHash: genDoc.Hash(), NextValidators: nextValidatorSet, diff --git a/state/state_test.go b/state/state_test.go index 5484da6d4..bc50430f8 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -1028,8 +1028,8 @@ func TestState_MakeHashMessage(t *testing.T) { require.False(t, bytes.Equal(message1, message2)) privVal := makePrivVal() - state.LastProof, _ = privVal.GenerateVRFProof(message1) - output, _ := vrf.ProofToHash(state.LastProof) + proof, _ := privVal.GenerateVRFProof(message1) + output, _ := vrf.ProofToHash(proof) state.LastProofHash = output message3, err := state.MakeHashMessage(0) require.NoError(t, err) diff --git a/state/validation.go b/state/validation.go index f82e752aa..15bfeb934 100644 --- a/state/validation.go +++ b/state/validation.go @@ -166,9 +166,9 @@ func validateBlock(evidencePool EvidencePool, stateDB dbm.DB, state State, round _, val := state.Validators.GetByAddress(block.ProposerAddress) verified, err := vrf.Verify(val.PubKey.(ed25519.PubKeyEd25519), block.Proof.Bytes(), message) if err != nil { - return types.NewErrInvalidProof(fmt.Sprintf("verification failed: %s; proof: %v, prevProof: %v, height=%d, round=%d, addr: %v", err.Error(), block.Proof, state.LastProof, state.LastBlockHeight, block.Round, block.ProposerAddress)) + return types.NewErrInvalidProof(fmt.Sprintf("verification failed: %s; proof: %v, prevProofHash: %v, height=%d, round=%d, addr: %v", err.Error(), block.Proof, state.LastProofHash, state.LastBlockHeight, block.Round, block.ProposerAddress)) } else if !verified { - return types.NewErrInvalidProof(fmt.Sprintf("proof: %v, prevProof: %v, height=%d, round=%d, addr: %v", block.Proof, state.LastProof, state.LastBlockHeight, block.Round, block.ProposerAddress)) + return types.NewErrInvalidProof(fmt.Sprintf("proof: %v, prevProofHash: %v, height=%d, round=%d, addr: %v", block.Proof, state.LastProofHash, state.LastBlockHeight, block.Round, block.ProposerAddress)) } return nil From 761dc5b5786223bf6ea8454e33508a0365f0b789 Mon Sep 17 00:00:00 2001 From: zemyblue Date: Thu, 2 Apr 2020 18:36:34 +0900 Subject: [PATCH 3/5] fix lint errors --- .circleci/config.yml | 4 +--- state/helpers_test.go | 7 ++++--- state/state_test.go | 2 +- state/validation.go | 7 +++++-- types/errors.go | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 84c9828ce..7e9786d9e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -402,9 +402,7 @@ workflows: only: - docs-theme-latest - lint - - setup_dependencies: - requires: - - lint + - setup_dependencies - test_abci_apps: requires: - setup_dependencies diff --git a/state/helpers_test.go b/state/helpers_test.go index 49ef52f41..49e42b312 100644 --- a/state/helpers_test.go +++ b/state/helpers_test.go @@ -45,7 +45,8 @@ func makeAndCommitGoodBlock( privVals map[string]types.PrivValidator, evidence []types.Evidence) (sm.State, types.BlockID, *types.Commit, error) { // A good block passes - state, blockID, err := makeAndApplyGoodBlock(state, privVals[state.Validators.Proposer.Address.String()], height, lastCommit, proposerAddr, blockExec, evidence) + state, blockID, err := makeAndApplyGoodBlock(state, privVals[state.Validators.Proposer.Address.String()], height, + lastCommit, proposerAddr, blockExec, evidence) if err != nil { return state, types.BlockID{}, nil, err } @@ -58,8 +59,8 @@ func makeAndCommitGoodBlock( return state, blockID, commit, nil } -func makeAndApplyGoodBlock(state sm.State, privVal types.PrivValidator, height int64, lastCommit *types.Commit, proposerAddr []byte, - blockExec *sm.BlockExecutor, evidence []types.Evidence) (sm.State, types.BlockID, error) { +func makeAndApplyGoodBlock(state sm.State, privVal types.PrivValidator, height int64, lastCommit *types.Commit, + proposerAddr []byte, blockExec *sm.BlockExecutor, evidence []types.Evidence) (sm.State, types.BlockID, error) { message, _ := state.MakeHashMessage(0) proof, _ := privVal.GenerateVRFProof(message) block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, evidence, proposerAddr, 0, proof) diff --git a/state/state_test.go b/state/state_test.go index bc50430f8..74026eefe 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -3,7 +3,6 @@ package state_test import ( "bytes" "fmt" - "github.com/tendermint/tendermint/crypto/vrf" "math" "math/big" "os" @@ -14,6 +13,7 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/vrf" "github.com/tendermint/tendermint/libs/kv" "github.com/tendermint/tendermint/libs/rand" tmrand "github.com/tendermint/tendermint/libs/rand" diff --git a/state/validation.go b/state/validation.go index 15bfeb934..65218e274 100644 --- a/state/validation.go +++ b/state/validation.go @@ -166,9 +166,12 @@ func validateBlock(evidencePool EvidencePool, stateDB dbm.DB, state State, round _, val := state.Validators.GetByAddress(block.ProposerAddress) verified, err := vrf.Verify(val.PubKey.(ed25519.PubKeyEd25519), block.Proof.Bytes(), message) if err != nil { - return types.NewErrInvalidProof(fmt.Sprintf("verification failed: %s; proof: %v, prevProofHash: %v, height=%d, round=%d, addr: %v", err.Error(), block.Proof, state.LastProofHash, state.LastBlockHeight, block.Round, block.ProposerAddress)) + return types.NewErrInvalidProof(fmt.Sprintf( + "verification failed: %s; proof: %v, prevProofHash: %v, height=%d, round=%d, addr: %v", + err.Error(), block.Proof, state.LastProofHash, state.LastBlockHeight, block.Round, block.ProposerAddress)) } else if !verified { - return types.NewErrInvalidProof(fmt.Sprintf("proof: %v, prevProofHash: %v, height=%d, round=%d, addr: %v", block.Proof, state.LastProofHash, state.LastBlockHeight, block.Round, block.ProposerAddress)) + return types.NewErrInvalidProof(fmt.Sprintf("proof: %v, prevProofHash: %v, height=%d, round=%d, addr: %v", + block.Proof, state.LastProofHash, state.LastBlockHeight, block.Round, block.ProposerAddress)) } return nil diff --git a/types/errors.go b/types/errors.go index 079b781e7..e4dc74c76 100644 --- a/types/errors.go +++ b/types/errors.go @@ -81,4 +81,4 @@ func NewErrInvalidRound(consensusRound, blockRound int) ErrInvalidRound { func (e ErrInvalidRound) Error() string { return fmt.Sprintf("Block round(%d) is mismatched to consensus round(%d)", e.BlockRound, e.ConsensusRound) -} \ No newline at end of file +} From fddae85f7c00950c5ac34b4611b9ff471d047841 Mon Sep 17 00:00:00 2001 From: zemyblue Date: Thu, 2 Apr 2020 18:55:21 +0900 Subject: [PATCH 4/5] Add changes to `CHANGELOG_PENDING` --- CHANGELOG_PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 258d4d681..99c09d613 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -21,6 +21,7 @@ program](https://hackerone.com/tendermint). ### FEATURES: - [types] [\#40](https://github.com/line/tendermint/issues/40) Add vrf interface and add a function generating vrf proof to PrivValidator +- [state] [\#44](https://github.com/line/tendermint/issues/44) Add genesis seed for electing proposer of first block ### IMPROVEMENTS: From db5e5534e7ad676721c3b84b567dfa2c28c9f360 Mon Sep 17 00:00:00 2001 From: zemyblue Date: Fri, 3 Apr 2020 21:38:09 +0900 Subject: [PATCH 5/5] Update state.go Change the comment more clear. --- state/state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/state/state.go b/state/state.go index 3eb3c16b1..7a7342a95 100644 --- a/state/state.go +++ b/state/state.go @@ -62,7 +62,7 @@ type State struct { LastBlockID types.BlockID LastBlockTime time.Time - // vrf proof + // vrf hash from proof LastProofHash []byte // LastValidators is used to validate block.LastCommit.