Skip to content

Commit

Permalink
feat: serialize state with protobuf (cosmos#424)
Browse files Browse the repository at this point in the history
* reproduce state deserialization error
* save state regardless of DA submission
* serialize state with protobuf
* move `State` to `types` package
* create protobuf definition for `State`
* add `FromProto` and `ToProto` methods
* fill validator sets in tests
  • Loading branch information
tzdybal authored Jun 10, 2022
1 parent 47f481b commit 3c4318f
Show file tree
Hide file tree
Showing 14 changed files with 1,604 additions and 48 deletions.
18 changes: 9 additions & 9 deletions block/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type newBlockEvent struct {

// Manager is responsible for aggregating transactions into blocks.
type Manager struct {
lastState state.State
lastState types.State

conf config.BlockManagerConfig
genesis *tmtypes.GenesisDoc
Expand Down Expand Up @@ -72,10 +72,10 @@ type Manager struct {
}

// getInitialState tries to load lastState from Store, and if it's not available it reads GenesisDoc.
func getInitialState(store store.Store, genesis *tmtypes.GenesisDoc) (state.State, error) {
func getInitialState(store store.Store, genesis *tmtypes.GenesisDoc) (types.State, error) {
s, err := store.LoadState()
if err != nil {
s, err = state.NewFromGenesisDoc(genesis)
s, err = types.NewFromGenesisDoc(genesis)
}
return s, err
}
Expand Down Expand Up @@ -372,11 +372,6 @@ func (m *Manager) publishBlock(ctx context.Context) error {
return err
}

err = m.submitBlockToDA(ctx, block)
if err != nil {
return err
}

newState.DAHeight = atomic.LoadUint64(&m.daHeight)
m.lastState = newState
err = m.store.UpdateState(m.lastState)
Expand All @@ -389,6 +384,11 @@ func (m *Manager) publishBlock(ctx context.Context) error {
return err
}

err = m.submitBlockToDA(ctx, block)
if err != nil {
return err
}

m.publishHeader(block)

return nil
Expand Down Expand Up @@ -433,7 +433,7 @@ func (m *Manager) publishHeader(block *types.Block) {
m.HeaderOutCh <- &block.Header
}

func updateState(s *state.State, res *abci.ResponseInitChain) {
func updateState(s *types.State, res *abci.ResponseInitChain) {
// If the app did not return an app hash, we keep the one set from the genesis doc in
// the state. We don't set appHash since we don't want the genesis doc app hash
// recorded in the genesis block. We should probably just remove GenesisDoc.AppHash.
Expand Down
25 changes: 20 additions & 5 deletions block/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,29 @@ import (
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/celestiaorg/optimint/config"
"github.com/celestiaorg/optimint/da"
mockda "github.com/celestiaorg/optimint/da/mock"
"github.com/celestiaorg/optimint/state"
"github.com/celestiaorg/optimint/store"
"github.com/celestiaorg/optimint/types"
)

func TestInitialState(t *testing.T) {
genesis := &types.GenesisDoc{
genesis := &tmtypes.GenesisDoc{
ChainID: "genesis id",
InitialHeight: 100,
}
sampleState := state.State{
sampleState := types.State{
ChainID: "state id",
InitialHeight: 123,
LastBlockHeight: 128,
LastValidators: getRandomValidatorSet(),
Validators: getRandomValidatorSet(),
NextValidators: getRandomValidatorSet(),
}

emptyStore := store.New(store.NewDefaultInMemoryKVStore())
Expand All @@ -38,7 +42,7 @@ func TestInitialState(t *testing.T) {
cases := []struct {
name string
store store.Store
genesis *types.GenesisDoc
genesis *tmtypes.GenesisDoc
expectedInitialHeight int64
expectedLastBlockHeight int64
expectedChainID string
Expand Down Expand Up @@ -88,3 +92,14 @@ func getMockDALC(logger log.Logger) da.DataAvailabilityLayerClient {
_ = dalc.Start()
return dalc
}

// copied from store_test.go
func getRandomValidatorSet() *tmtypes.ValidatorSet {
pubKey := ed25519.GenPrivKey().PubKey()
return &tmtypes.ValidatorSet{
Proposer: &tmtypes.Validator{PubKey: pubKey, Address: pubKey.Address()},
Validators: []*tmtypes.Validator{
{PubKey: pubKey, Address: pubKey.Address()},
},
}
}
27 changes: 27 additions & 0 deletions proto/get_deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash

cd "$(dirname "${BASH_SOURCE[0]}")"

TM_VERSION=v0.34.14
TM_PROTO_URL=https://raw.githubusercontent.com/tendermint/tendermint/$TM_VERSION/proto/tendermint

TM_PROTO_FILES=(
abci/types.proto
version/types.proto
types/types.proto
types/evidence.proto
types/params.proto
types/validator.proto
state/types.proto
crypto/proof.proto
crypto/keys.proto
libs/bits/types.proto
p2p/types.proto
)

echo Fetching protobuf dependencies from Tendermint $TM_VERSION
for FILE in "${TM_PROTO_FILES[@]}"; do
echo Fetching "$FILE"
mkdir -p "tendermint/$(dirname $FILE)"
curl -sSL "$TM_PROTO_URL/$FILE" > "tendermint/$FILE"
done
38 changes: 38 additions & 0 deletions proto/optimint/state.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
syntax = "proto3";
package optimint;
option go_package = "github.com/celestiaorg/optimint/types/pb/optimint";

import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "tendermint/abci/types.proto";
import "tendermint/types/types.proto";
import "tendermint/types/validator.proto";
import "tendermint/types/params.proto";
import "tendermint/state/types.proto";


message State {
tendermint.state.Version version = 1;

string chain_id = 2;
int64 initial_height = 3;

int64 last_block_height = 4;

tendermint.types.BlockID last_block_id = 5 [(gogoproto.nullable) = false, (gogoproto.customname) = "LastBlockID"];
google.protobuf.Timestamp last_block_time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];

uint64 da_height = 7 [(gogoproto.customname) = "DAHeight"];

tendermint.types.ValidatorSet next_validators = 8;
tendermint.types.ValidatorSet validators = 9;
tendermint.types.ValidatorSet last_validators = 10;
int64 last_height_validators_changed = 11;

tendermint.types.ConsensusParams consensus_params = 12 [(gogoproto.nullable) = false];
int64 last_height_consensus_params_changed = 13;

bytes last_results_hash = 14;

bytes app_hash = 15;
}
Loading

0 comments on commit 3c4318f

Please sign in to comment.