From 3c4318f9cf9047a54405a86e9ed20a99813944c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zdyba=C5=82?= Date: Fri, 10 Jun 2022 07:07:27 +0200 Subject: [PATCH] feat: serialize state with protobuf (#424) * 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 --- block/manager.go | 18 +- block/manager_test.go | 25 +- proto/get_deps.sh | 27 + proto/optimint/state.proto | 38 ++ proto/tendermint/abci/types.proto | 363 ++++++++++ rpc/client/client_test.go | 3 +- state/executor.go | 24 +- state/executor_test.go | 4 +- store/store.go | 27 +- store/store_test.go | 23 +- store/types.go | 5 +- types/pb/optimint/state.pb.go | 1027 +++++++++++++++++++++++++++++ types/serialization.go | 66 ++ {state => types}/state.go | 2 +- 14 files changed, 1604 insertions(+), 48 deletions(-) create mode 100755 proto/get_deps.sh create mode 100644 proto/optimint/state.proto create mode 100644 types/pb/optimint/state.pb.go rename {state => types}/state.go (99%) diff --git a/block/manager.go b/block/manager.go index 47be36aa65b..f1b13abe61b 100644 --- a/block/manager.go +++ b/block/manager.go @@ -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 @@ -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 } @@ -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) @@ -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 @@ -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. diff --git a/block/manager_test.go b/block/manager_test.go index 9ea21a1f19b..6a6623f6388 100644 --- a/block/manager_test.go +++ b/block/manager_test.go @@ -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()) @@ -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 @@ -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()}, + }, + } +} diff --git a/proto/get_deps.sh b/proto/get_deps.sh new file mode 100755 index 00000000000..c0ce5ca9315 --- /dev/null +++ b/proto/get_deps.sh @@ -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 diff --git a/proto/optimint/state.proto b/proto/optimint/state.proto new file mode 100644 index 00000000000..c6226fdb9f0 --- /dev/null +++ b/proto/optimint/state.proto @@ -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; +} diff --git a/proto/tendermint/abci/types.proto b/proto/tendermint/abci/types.proto index c811bbb21ca..8e3a9093638 100644 --- a/proto/tendermint/abci/types.proto +++ b/proto/tendermint/abci/types.proto @@ -5,6 +5,10 @@ option go_package = "github.com/tendermint/tendermint/abci/types"; // For more information on gogo.proto, see: // https://github.com/gogo/protobuf/blob/master/extensions.md +import "tendermint/crypto/proof.proto"; +import "tendermint/types/types.proto"; +import "tendermint/crypto/keys.proto"; +import "tendermint/types/params.proto"; import "google/protobuf/timestamp.proto"; import "gogoproto/gogo.proto"; @@ -12,6 +16,322 @@ import "gogoproto/gogo.proto"; // NOTE: When using custom types, mind the warnings. // https://github.com/gogo/protobuf/blob/master/custom_types.md#warnings-and-issues +//---------------------------------------- +// Request types + +message Request { + oneof value { + RequestEcho echo = 1; + RequestFlush flush = 2; + RequestInfo info = 3; + RequestSetOption set_option = 4; + RequestInitChain init_chain = 5; + RequestQuery query = 6; + RequestBeginBlock begin_block = 7; + RequestCheckTx check_tx = 8; + RequestDeliverTx deliver_tx = 9; + RequestEndBlock end_block = 10; + RequestCommit commit = 11; + RequestListSnapshots list_snapshots = 12; + RequestOfferSnapshot offer_snapshot = 13; + RequestLoadSnapshotChunk load_snapshot_chunk = 14; + RequestApplySnapshotChunk apply_snapshot_chunk = 15; + } +} + +message RequestEcho { + string message = 1; +} + +message RequestFlush {} + +message RequestInfo { + string version = 1; + uint64 block_version = 2; + uint64 p2p_version = 3; +} + +// nondeterministic +message RequestSetOption { + string key = 1; + string value = 2; +} + +message RequestInitChain { + google.protobuf.Timestamp time = 1 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 2; + ConsensusParams consensus_params = 3; + repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; + int64 initial_height = 6; +} + +message RequestQuery { + bytes data = 1; + string path = 2; + int64 height = 3; + bool prove = 4; +} + +message RequestBeginBlock { + bytes hash = 1; + tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; + LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; + repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; +} + +enum CheckTxType { + NEW = 0 [(gogoproto.enumvalue_customname) = "New"]; + RECHECK = 1 [(gogoproto.enumvalue_customname) = "Recheck"]; +} + +message RequestCheckTx { + bytes tx = 1; + CheckTxType type = 2; +} + +message RequestDeliverTx { + bytes tx = 1; +} + +message RequestEndBlock { + int64 height = 1; +} + +message RequestCommit {} + +// lists available snapshots +message RequestListSnapshots { +} + +// offers a snapshot to the application +message RequestOfferSnapshot { + Snapshot snapshot = 1; // snapshot offered by peers + bytes app_hash = 2; // light client-verified app hash for snapshot height +} + +// loads a snapshot chunk +message RequestLoadSnapshotChunk { + uint64 height = 1; + uint32 format = 2; + uint32 chunk = 3; +} + +// Applies a snapshot chunk +message RequestApplySnapshotChunk { + uint32 index = 1; + bytes chunk = 2; + string sender = 3; +} + +//---------------------------------------- +// Response types + +message Response { + oneof value { + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseSetOption set_option = 5; + ResponseInitChain init_chain = 6; + ResponseQuery query = 7; + ResponseBeginBlock begin_block = 8; + ResponseCheckTx check_tx = 9; + ResponseDeliverTx deliver_tx = 10; + ResponseEndBlock end_block = 11; + ResponseCommit commit = 12; + ResponseListSnapshots list_snapshots = 13; + ResponseOfferSnapshot offer_snapshot = 14; + ResponseLoadSnapshotChunk load_snapshot_chunk = 15; + ResponseApplySnapshotChunk apply_snapshot_chunk = 16; + } +} + +// nondeterministic +message ResponseException { + string error = 1; +} + +message ResponseEcho { + string message = 1; +} + +message ResponseFlush {} + +message ResponseInfo { + string data = 1; + + string version = 2; + uint64 app_version = 3; + + int64 last_block_height = 4; + bytes last_block_app_hash = 5; +} + +// nondeterministic +message ResponseSetOption { + uint32 code = 1; + // bytes data = 2; + string log = 3; + string info = 4; +} + +message ResponseInitChain { + ConsensusParams consensus_params = 1; + repeated ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; + bytes app_hash = 3; +} + +message ResponseQuery { + uint32 code = 1; + // bytes data = 2; // use "value" instead. + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 index = 5; + bytes key = 6; + bytes value = 7; + tendermint.crypto.ProofOps proof_ops = 8; + int64 height = 9; + string codespace = 10; +} + +message ResponseBeginBlock { + repeated Event events = 1 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; +} + +message ResponseCheckTx { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + string codespace = 8; +} + +message ResponseDeliverTx { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; // nondeterministic + string codespace = 8; +} + +message ResponseEndBlock { + repeated ValidatorUpdate validator_updates = 1 + [(gogoproto.nullable) = false]; + ConsensusParams consensus_param_updates = 2; + repeated Event events = 3 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; +} + +message ResponseCommit { + // reserve 1 + bytes data = 2; + int64 retain_height = 3; +} + +message ResponseListSnapshots { + repeated Snapshot snapshots = 1; +} + +message ResponseOfferSnapshot { + Result result = 1; + + enum Result { + UNKNOWN = 0; // Unknown result, abort all snapshot restoration + ACCEPT = 1; // Snapshot accepted, apply chunks + ABORT = 2; // Abort all snapshot restoration + REJECT = 3; // Reject this specific snapshot, try others + REJECT_FORMAT = 4; // Reject all snapshots of this format, try others + REJECT_SENDER = 5; // Reject all snapshots from the sender(s), try others + } +} + +message ResponseLoadSnapshotChunk { + bytes chunk = 1; +} + +message ResponseApplySnapshotChunk { + Result result = 1; + repeated uint32 refetch_chunks = 2; // Chunks to refetch and reapply + repeated string reject_senders = 3; // Chunk senders to reject and ban + + enum Result { + UNKNOWN = 0; // Unknown result, abort all snapshot restoration + ACCEPT = 1; // Chunk successfully accepted + ABORT = 2; // Abort all snapshot restoration + RETRY = 3; // Retry chunk (combine with refetch and reject) + RETRY_SNAPSHOT = 4; // Retry snapshot (combine with refetch and reject) + REJECT_SNAPSHOT = 5; // Reject this snapshot, try others + } +} + +//---------------------------------------- +// Misc. + +// ConsensusParams contains all consensus-relevant parameters +// that can be adjusted by the abci app +message ConsensusParams { + BlockParams block = 1; + tendermint.types.EvidenceParams evidence = 2; + tendermint.types.ValidatorParams validator = 3; + tendermint.types.VersionParams version = 4; +} + +// BlockParams contains limits on the block size. +message BlockParams { + // Note: must be greater than 0 + int64 max_bytes = 1; + // Note: must be greater or equal to -1 + int64 max_gas = 2; +} + +message LastCommitInfo { + int32 round = 1; + repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + +// Event allows application developers to attach additional information to +// ResponseBeginBlock, ResponseEndBlock, ResponseCheckTx and ResponseDeliverTx. +// Later, transactions may be queried using these events. +message Event { + string type = 1; + repeated EventAttribute attributes = 2 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "attributes,omitempty" + ]; +} + +// EventAttribute is a single key-value pair, associated with an event. +message EventAttribute { + bytes key = 1; + bytes value = 2; + bool index = 3; // nondeterministic +} + +// TxResult contains results of executing the transaction. +// +// One usage is indexing transaction results. +message TxResult { + int64 height = 1; + uint32 index = 2; + bytes tx = 3; + ResponseDeliverTx result = 4 [(gogoproto.nullable) = false]; +} + +//---------------------------------------- +// Blockchain Types + // Validator message Validator { bytes address = 1; // The first 20 bytes of SHA256(public key) @@ -19,6 +339,18 @@ message Validator { int64 power = 3; // The voting power } +// ValidatorUpdate +message ValidatorUpdate { + tendermint.crypto.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + int64 power = 2; +} + +// VoteInfo +message VoteInfo { + Validator validator = 1 [(gogoproto.nullable) = false]; + bool signed_last_block = 2; +} + enum EvidenceType { UNKNOWN = 0; DUPLICATE_VOTE = 1; @@ -42,3 +374,34 @@ message Evidence { int64 total_voting_power = 5; } +//---------------------------------------- +// State Sync Types + +message Snapshot { + uint64 height = 1; // The height at which the snapshot was taken + uint32 format = 2; // The application-specific snapshot format + uint32 chunks = 3; // Number of chunks in the snapshot + bytes hash = 4; // Arbitrary snapshot hash, equal only if identical + bytes metadata = 5; // Arbitrary application metadata +} + +//---------------------------------------- +// Service Definition + +service ABCIApplication { + rpc Echo(RequestEcho) returns (ResponseEcho); + rpc Flush(RequestFlush) returns (ResponseFlush); + rpc Info(RequestInfo) returns (ResponseInfo); + rpc SetOption(RequestSetOption) returns (ResponseSetOption); + rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); + rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); + rpc Query(RequestQuery) returns (ResponseQuery); + rpc Commit(RequestCommit) returns (ResponseCommit); + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); + rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); + rpc ListSnapshots(RequestListSnapshots) returns (ResponseListSnapshots); + rpc OfferSnapshot(RequestOfferSnapshot) returns (ResponseOfferSnapshot); + rpc LoadSnapshotChunk(RequestLoadSnapshotChunk) returns (ResponseLoadSnapshotChunk); + rpc ApplySnapshotChunk(RequestApplySnapshotChunk) returns (ResponseApplySnapshotChunk); +} diff --git a/rpc/client/client_test.go b/rpc/client/client_test.go index 048f026f7bb..7e3f8ab0722 100644 --- a/rpc/client/client_test.go +++ b/rpc/client/client_test.go @@ -29,7 +29,6 @@ import ( abciconv "github.com/celestiaorg/optimint/conv/abci" "github.com/celestiaorg/optimint/mocks" "github.com/celestiaorg/optimint/node" - "github.com/celestiaorg/optimint/state" "github.com/celestiaorg/optimint/types" ) @@ -715,7 +714,7 @@ func getRandomBlock(height uint64, nTxs int) *types.Block { block := &types.Block{ Header: types.Header{ Height: height, - Version: types.Version{Block: state.InitStateVersion.Consensus.Block}, + Version: types.Version{Block: types.InitStateVersion.Consensus.Block}, ProposerAddress: getRandomBytes(20), }, Data: types.Data{ diff --git a/state/executor.go b/state/executor.go index 256d6ad3c7e..00075f0f07e 100644 --- a/state/executor.go +++ b/state/executor.go @@ -83,7 +83,7 @@ func (e *BlockExecutor) InitChain(genesis *tmtypes.GenesisDoc) (*abci.ResponseIn } // CreateBlock reaps transactions from mempool and builds a block. -func (e *BlockExecutor) CreateBlock(height uint64, lastCommit *types.Commit, lastHeaderHash [32]byte, state State) *types.Block { +func (e *BlockExecutor) CreateBlock(height uint64, lastCommit *types.Commit, lastHeaderHash [32]byte, state types.State) *types.Block { maxBytes := state.ConsensusParams.Block.MaxBytes maxGas := state.ConsensusParams.Block.MaxGas @@ -120,15 +120,15 @@ func (e *BlockExecutor) CreateBlock(height uint64, lastCommit *types.Commit, las } // ApplyBlock validates, executes and commits the block. -func (e *BlockExecutor) ApplyBlock(ctx context.Context, state State, block *types.Block) (State, *tmstate.ABCIResponses, uint64, error) { +func (e *BlockExecutor) ApplyBlock(ctx context.Context, state types.State, block *types.Block) (types.State, *tmstate.ABCIResponses, uint64, error) { err := e.validate(state, block) if err != nil { - return State{}, nil, 0, err + return types.State{}, nil, 0, err } resp, err := e.execute(ctx, state, block) if err != nil { - return State{}, nil, 0, err + return types.State{}, nil, 0, err } abciValUpdates := resp.EndBlock.ValidatorUpdates @@ -147,12 +147,12 @@ func (e *BlockExecutor) ApplyBlock(ctx context.Context, state State, block *type state, err = e.updateState(state, block, resp, validatorUpdates) if err != nil { - return State{}, nil, 0, err + return types.State{}, nil, 0, err } appHash, retainHeight, err := e.commit(ctx, state, block, resp.DeliverTxs) if err != nil { - return State{}, nil, 0, err + return types.State{}, nil, 0, err } copy(state.AppHash[:], appHash[:]) @@ -165,7 +165,7 @@ func (e *BlockExecutor) ApplyBlock(ctx context.Context, state State, block *type return state, resp, retainHeight, nil } -func (e *BlockExecutor) updateState(state State, block *types.Block, abciResponses *tmstate.ABCIResponses, validatorUpdates []*tmtypes.Validator) (State, error) { +func (e *BlockExecutor) updateState(state types.State, block *types.Block, abciResponses *tmstate.ABCIResponses, validatorUpdates []*tmtypes.Validator) (types.State, error) { nValSet := state.NextValidators.Copy() lastHeightValSetChanged := state.LastHeightValidatorsChanged // Optimint can work without validators @@ -184,7 +184,7 @@ func (e *BlockExecutor) updateState(state State, block *types.Block, abciRespons } hash := block.Header.Hash() - s := State{ + s := types.State{ Version: state.Version, ChainID: state.ChainID, InitialHeight: state.InitialHeight, @@ -207,7 +207,7 @@ func (e *BlockExecutor) updateState(state State, block *types.Block, abciRespons return s, nil } -func (e *BlockExecutor) commit(ctx context.Context, state State, block *types.Block, deliverTxs []*abci.ResponseDeliverTx) ([]byte, uint64, error) { +func (e *BlockExecutor) commit(ctx context.Context, state types.State, block *types.Block, deliverTxs []*abci.ResponseDeliverTx) ([]byte, uint64, error) { e.mempool.Lock() defer e.mempool.Unlock() @@ -231,7 +231,7 @@ func (e *BlockExecutor) commit(ctx context.Context, state State, block *types.Bl return resp.Data, uint64(resp.RetainHeight), err } -func (e *BlockExecutor) validate(state State, block *types.Block) error { +func (e *BlockExecutor) validate(state types.State, block *types.Block) error { err := block.ValidateBasic() if err != nil { return err @@ -257,7 +257,7 @@ func (e *BlockExecutor) validate(state State, block *types.Block) error { return nil } -func (e *BlockExecutor) execute(ctx context.Context, state State, block *types.Block) (*tmstate.ABCIResponses, error) { +func (e *BlockExecutor) execute(ctx context.Context, state types.State, block *types.Block) (*tmstate.ABCIResponses, error) { abciResponses := new(tmstate.ABCIResponses) abciResponses.DeliverTxs = make([]*abci.ResponseDeliverTx, len(block.Data.Txs)) @@ -326,7 +326,7 @@ func (e *BlockExecutor) getLastCommitHash(lastCommit *types.Commit, header *type return lastABCICommit.Hash() } -func (e *BlockExecutor) publishEvents(resp *tmstate.ABCIResponses, block *types.Block, state State) error { +func (e *BlockExecutor) publishEvents(resp *tmstate.ABCIResponses, block *types.Block, state types.State) error { if e.eventBus == nil { return nil } diff --git a/state/executor_test.go b/state/executor_test.go index 5b7afd0dc68..4518709849b 100644 --- a/state/executor_test.go +++ b/state/executor_test.go @@ -40,7 +40,7 @@ func TestCreateBlock(t *testing.T) { mpool := mempool.NewCListMempool(cfg.DefaultMempoolConfig(), proxy.NewAppConnMempool(client), 0) executor := NewBlockExecutor([]byte("test address"), nsID, "test", mpool, proxy.NewAppConnConsensus(client), nil, logger) - state := State{} + state := types.State{} state.ConsensusParams.Block.MaxBytes = 100 state.ConsensusParams.Block.MaxGas = 100000 state.Validators = tmtypes.NewValidatorSet(nil) @@ -111,7 +111,7 @@ func TestApplyBlock(t *testing.T) { require.NoError(err) require.NotNil(headerSub) - state := State{ + state := types.State{ NextValidators: tmtypes.NewValidatorSet(nil), Validators: tmtypes.NewValidatorSet(nil), LastValidators: tmtypes.NewValidatorSet(nil), diff --git a/store/store.go b/store/store.go index 6803a882f24..0209f60337d 100644 --- a/store/store.go +++ b/store/store.go @@ -2,7 +2,6 @@ package store import ( "encoding/binary" - "encoding/json" "errors" "fmt" "sync/atomic" @@ -12,8 +11,8 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "go.uber.org/multierr" - "github.com/celestiaorg/optimint/state" "github.com/celestiaorg/optimint/types" + pb "github.com/celestiaorg/optimint/types/pb/optimint" ) var ( @@ -150,24 +149,32 @@ func (s *DefaultStore) LoadCommitByHash(hash [32]byte) (*types.Commit, error) { // UpdateState updates state saved in Store. Only one State is stored. // If there is no State in Store, state will be saved. -func (s *DefaultStore) UpdateState(state state.State) error { - blob, err := json.Marshal(state) +func (s *DefaultStore) UpdateState(state types.State) error { + pbState, err := state.ToProto() if err != nil { return err } - return s.db.Set(getStateKey(), blob) + data, err := pbState.Marshal() + if err != nil { + return err + } + return s.db.Set(getStateKey(), data) } // LoadState returns last state saved with UpdateState. -func (s *DefaultStore) LoadState() (state.State, error) { - var state state.State - +func (s *DefaultStore) LoadState() (types.State, error) { blob, err := s.db.Get(getStateKey()) if err != nil { - return state, err + return types.State{}, err + } + var pbState pb.State + err = pbState.Unmarshal(blob) + if err != nil { + return types.State{}, err } - err = json.Unmarshal(blob, &state) + var state types.State + err = state.FromProto(&pbState) atomic.StoreUint64(&s.height, uint64(state.LastBlockHeight)) return state, err } diff --git a/store/store_test.go b/store/store_test.go index d0b23582a34..ab35b3ed9e5 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -6,9 +6,10 @@ import ( "testing" abcitypes "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/ed25519" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" + tmtypes "github.com/tendermint/tendermint/types" - "github.com/celestiaorg/optimint/state" "github.com/celestiaorg/optimint/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -127,13 +128,16 @@ func TestRestart(t *testing.T) { assert := assert.New(t) + validatorSet := getRandomValidatorSet() + kv := NewDefaultInMemoryKVStore() s1 := New(kv) expectedHeight := uint64(10) - //block := getRandomBlock(expectedHeight, 10) - //err := s1.SaveBlock(block, &types.Commit{Height: block.Header.Height, HeaderHash: block.Header.Hash()}) - err := s1.UpdateState(state.State{ + err := s1.UpdateState(types.State{ LastBlockHeight: int64(expectedHeight), + NextValidators: validatorSet, + Validators: validatorSet, + LastValidators: validatorSet, }) assert.NoError(err) @@ -218,3 +222,14 @@ func getRandomBytes(n int) []byte { _, _ = rand.Read(data) return data } + +// TODO(tzdybal): extract to some common place +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()}, + }, + } +} diff --git a/store/types.go b/store/types.go index 5c7db79ab2b..4a23249dff4 100644 --- a/store/types.go +++ b/store/types.go @@ -4,7 +4,6 @@ import ( tmstate "github.com/tendermint/tendermint/proto/tendermint/state" tmtypes "github.com/tendermint/tendermint/types" - "github.com/celestiaorg/optimint/state" "github.com/celestiaorg/optimint/types" ) @@ -34,9 +33,9 @@ type Store interface { // UpdateState updates state saved in Store. Only one State is stored. // If there is no State in Store, state will be saved. - UpdateState(state state.State) error + UpdateState(state types.State) error // LoadState returns last state saved with UpdateState. - LoadState() (state.State, error) + LoadState() (types.State, error) SaveValidators(height uint64, validatorSet *tmtypes.ValidatorSet) error diff --git a/types/pb/optimint/state.pb.go b/types/pb/optimint/state.pb.go new file mode 100644 index 00000000000..06158ad228a --- /dev/null +++ b/types/pb/optimint/state.pb.go @@ -0,0 +1,1027 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: optimint/state.proto + +package optimint + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/tendermint/tendermint/abci/types" + state "github.com/tendermint/tendermint/proto/tendermint/state" + types "github.com/tendermint/tendermint/proto/tendermint/types" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type State struct { + Version *state.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + InitialHeight int64 `protobuf:"varint,3,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` + LastBlockHeight int64 `protobuf:"varint,4,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` + LastBlockID types.BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId,proto3" json:"last_block_id"` + LastBlockTime time.Time `protobuf:"bytes,6,opt,name=last_block_time,json=lastBlockTime,proto3,stdtime" json:"last_block_time"` + DAHeight uint64 `protobuf:"varint,7,opt,name=da_height,json=daHeight,proto3" json:"da_height,omitempty"` + NextValidators *types.ValidatorSet `protobuf:"bytes,8,opt,name=next_validators,json=nextValidators,proto3" json:"next_validators,omitempty"` + Validators *types.ValidatorSet `protobuf:"bytes,9,opt,name=validators,proto3" json:"validators,omitempty"` + LastValidators *types.ValidatorSet `protobuf:"bytes,10,opt,name=last_validators,json=lastValidators,proto3" json:"last_validators,omitempty"` + LastHeightValidatorsChanged int64 `protobuf:"varint,11,opt,name=last_height_validators_changed,json=lastHeightValidatorsChanged,proto3" json:"last_height_validators_changed,omitempty"` + ConsensusParams types.ConsensusParams `protobuf:"bytes,12,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightConsensusParamsChanged int64 `protobuf:"varint,13,opt,name=last_height_consensus_params_changed,json=lastHeightConsensusParamsChanged,proto3" json:"last_height_consensus_params_changed,omitempty"` + LastResultsHash []byte `protobuf:"bytes,14,opt,name=last_results_hash,json=lastResultsHash,proto3" json:"last_results_hash,omitempty"` + AppHash []byte `protobuf:"bytes,15,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *State) Reset() { *m = State{} } +func (m *State) String() string { return proto.CompactTextString(m) } +func (*State) ProtoMessage() {} +func (*State) Descriptor() ([]byte, []int) { + return fileDescriptor_eff9abc4ea60e43b, []int{0} +} +func (m *State) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *State) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_State.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *State) XXX_Merge(src proto.Message) { + xxx_messageInfo_State.Merge(m, src) +} +func (m *State) XXX_Size() int { + return m.Size() +} +func (m *State) XXX_DiscardUnknown() { + xxx_messageInfo_State.DiscardUnknown(m) +} + +var xxx_messageInfo_State proto.InternalMessageInfo + +func (m *State) GetVersion() *state.Version { + if m != nil { + return m.Version + } + return nil +} + +func (m *State) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *State) GetInitialHeight() int64 { + if m != nil { + return m.InitialHeight + } + return 0 +} + +func (m *State) GetLastBlockHeight() int64 { + if m != nil { + return m.LastBlockHeight + } + return 0 +} + +func (m *State) GetLastBlockID() types.BlockID { + if m != nil { + return m.LastBlockID + } + return types.BlockID{} +} + +func (m *State) GetLastBlockTime() time.Time { + if m != nil { + return m.LastBlockTime + } + return time.Time{} +} + +func (m *State) GetDAHeight() uint64 { + if m != nil { + return m.DAHeight + } + return 0 +} + +func (m *State) GetNextValidators() *types.ValidatorSet { + if m != nil { + return m.NextValidators + } + return nil +} + +func (m *State) GetValidators() *types.ValidatorSet { + if m != nil { + return m.Validators + } + return nil +} + +func (m *State) GetLastValidators() *types.ValidatorSet { + if m != nil { + return m.LastValidators + } + return nil +} + +func (m *State) GetLastHeightValidatorsChanged() int64 { + if m != nil { + return m.LastHeightValidatorsChanged + } + return 0 +} + +func (m *State) GetConsensusParams() types.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return types.ConsensusParams{} +} + +func (m *State) GetLastHeightConsensusParamsChanged() int64 { + if m != nil { + return m.LastHeightConsensusParamsChanged + } + return 0 +} + +func (m *State) GetLastResultsHash() []byte { + if m != nil { + return m.LastResultsHash + } + return nil +} + +func (m *State) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +func init() { + proto.RegisterType((*State)(nil), "optimint.State") +} + +func init() { proto.RegisterFile("optimint/state.proto", fileDescriptor_eff9abc4ea60e43b) } + +var fileDescriptor_eff9abc4ea60e43b = []byte{ + // 590 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0x4f, 0x6f, 0xd3, 0x30, + 0x18, 0xc6, 0x1b, 0xf6, 0xa7, 0x99, 0xfb, 0x0f, 0xc2, 0x0e, 0x59, 0x07, 0x69, 0x40, 0x20, 0x15, + 0x0e, 0x89, 0x60, 0x77, 0x24, 0xd2, 0x4a, 0xac, 0x62, 0x42, 0x28, 0x43, 0x3b, 0x70, 0x89, 0x9c, + 0xc4, 0x24, 0x16, 0x69, 0x1c, 0xc5, 0xee, 0x04, 0xdf, 0x62, 0x1f, 0x6b, 0xc7, 0x1d, 0x39, 0x15, + 0xd4, 0x7e, 0x0a, 0x6e, 0xc8, 0x76, 0x9c, 0x66, 0x2b, 0x87, 0xdd, 0x9a, 0xe7, 0x7d, 0xde, 0x5f, + 0x9f, 0xd7, 0xaf, 0x13, 0x70, 0x48, 0x0a, 0x86, 0xe7, 0x38, 0x67, 0x2e, 0x65, 0x90, 0x21, 0xa7, + 0x28, 0x09, 0x23, 0x86, 0xae, 0xd4, 0xe1, 0x61, 0x42, 0x12, 0x22, 0x44, 0x97, 0xff, 0x92, 0xf5, + 0xe1, 0x28, 0x21, 0x24, 0xc9, 0x90, 0x2b, 0x9e, 0xc2, 0xc5, 0x37, 0x97, 0xe1, 0x39, 0xa2, 0x0c, + 0xce, 0x8b, 0xca, 0x70, 0xcc, 0x50, 0x1e, 0xa3, 0x52, 0x80, 0x61, 0x18, 0x61, 0x97, 0xfd, 0x2c, + 0x10, 0xad, 0x8a, 0x4f, 0x1a, 0x45, 0xa1, 0xdf, 0xaa, 0xda, 0x5b, 0xd5, 0x4b, 0x98, 0xe1, 0x18, + 0x32, 0x52, 0x56, 0x8e, 0xa7, 0x5b, 0x8e, 0x02, 0x96, 0x70, 0xfe, 0x3f, 0xbc, 0x18, 0xaa, 0x89, + 0x7f, 0xfe, 0x77, 0x1f, 0xec, 0x9d, 0x73, 0xd5, 0x38, 0x01, 0xed, 0x4b, 0x54, 0x52, 0x4c, 0x72, + 0x53, 0xb3, 0xb5, 0x71, 0xe7, 0xed, 0x91, 0xb3, 0xe9, 0x74, 0xe4, 0x71, 0x5c, 0x48, 0x83, 0xaf, + 0x9c, 0xc6, 0x11, 0xd0, 0xa3, 0x14, 0xe2, 0x3c, 0xc0, 0xb1, 0xf9, 0xc0, 0xd6, 0xc6, 0x07, 0x7e, + 0x5b, 0x3c, 0xcf, 0x62, 0xe3, 0x25, 0xe8, 0xe3, 0x1c, 0x33, 0x0c, 0xb3, 0x20, 0x45, 0x38, 0x49, + 0x99, 0xb9, 0x63, 0x6b, 0xe3, 0x1d, 0xbf, 0x57, 0xa9, 0xa7, 0x42, 0x34, 0x5e, 0x83, 0x47, 0x19, + 0xa4, 0x2c, 0x08, 0x33, 0x12, 0x7d, 0x57, 0xce, 0x5d, 0xe1, 0x1c, 0xf0, 0x82, 0xc7, 0xf5, 0xca, + 0xeb, 0x83, 0x5e, 0xc3, 0x8b, 0x63, 0x73, 0x6f, 0x3b, 0xa8, 0x1c, 0x4e, 0x74, 0xcd, 0xa6, 0xde, + 0xe3, 0xeb, 0xe5, 0xa8, 0xb5, 0x5a, 0x8e, 0x3a, 0x67, 0x0a, 0x35, 0x9b, 0xfa, 0x9d, 0x9a, 0x3b, + 0x8b, 0x8d, 0x33, 0x30, 0x68, 0x30, 0xf9, 0xe2, 0xcc, 0x7d, 0x41, 0x1d, 0x3a, 0x72, 0xab, 0x8e, + 0xda, 0xaa, 0xf3, 0x45, 0x6d, 0xd5, 0xd3, 0x39, 0xf6, 0xea, 0xf7, 0x48, 0xf3, 0x7b, 0x35, 0x8b, + 0x57, 0x8d, 0x57, 0xe0, 0x20, 0x86, 0x6a, 0x8a, 0xb6, 0xad, 0x8d, 0x77, 0xbd, 0xee, 0x6a, 0x39, + 0xd2, 0xa7, 0xef, 0xe5, 0x08, 0xbe, 0x1e, 0xc3, 0x6a, 0x98, 0x0f, 0x60, 0x90, 0xa3, 0x1f, 0x2c, + 0xa8, 0xd7, 0x49, 0x4d, 0x5d, 0xfc, 0xb1, 0xb5, 0x3d, 0xce, 0x85, 0xf2, 0x9c, 0x23, 0xe6, 0xf7, + 0x79, 0x5b, 0xad, 0x50, 0xe3, 0x1d, 0x00, 0x0d, 0xc6, 0xc1, 0xbd, 0x18, 0x8d, 0x0e, 0x1e, 0x44, + 0x9c, 0x40, 0x03, 0x02, 0xee, 0x17, 0x84, 0xb7, 0x35, 0x82, 0x4c, 0x80, 0x25, 0x40, 0x72, 0xfc, + 0x06, 0x2f, 0x88, 0x52, 0x98, 0x27, 0x28, 0x36, 0x3b, 0x62, 0xaf, 0xc7, 0xdc, 0x25, 0x4f, 0x61, + 0xd3, 0x3d, 0x91, 0x16, 0xc3, 0x07, 0x0f, 0x23, 0x92, 0x53, 0x94, 0xd3, 0x05, 0x0d, 0xe4, 0x45, + 0x36, 0xbb, 0x22, 0xce, 0xb3, 0xed, 0x38, 0x13, 0xe5, 0xfc, 0x2c, 0x8c, 0xde, 0x2e, 0xdf, 0x8b, + 0x3f, 0x88, 0x6e, 0xcb, 0xc6, 0x27, 0xf0, 0xa2, 0x19, 0xec, 0x2e, 0xbf, 0x8e, 0xd7, 0x13, 0xf1, + 0xec, 0x4d, 0xbc, 0x3b, 0x7c, 0x95, 0x51, 0xdd, 0xd9, 0x12, 0xd1, 0x45, 0xc6, 0x68, 0x90, 0x42, + 0x9a, 0x9a, 0x7d, 0x5b, 0x1b, 0x77, 0xe5, 0x9d, 0xf5, 0xa5, 0x7e, 0x0a, 0x69, 0xca, 0xdf, 0x10, + 0x58, 0x14, 0xd2, 0x32, 0x10, 0x96, 0x36, 0x2c, 0x0a, 0x5e, 0xf2, 0x3e, 0x5e, 0xaf, 0x2c, 0xed, + 0x66, 0x65, 0x69, 0x7f, 0x56, 0x96, 0x76, 0xb5, 0xb6, 0x5a, 0x37, 0x6b, 0xab, 0xf5, 0x6b, 0x6d, + 0xb5, 0xbe, 0xbe, 0x49, 0x30, 0x4b, 0x17, 0xa1, 0x13, 0x91, 0xb9, 0x1b, 0xa1, 0x0c, 0x51, 0x86, + 0x21, 0x29, 0x13, 0xb7, 0xfe, 0x3a, 0x55, 0xef, 0x79, 0x58, 0x2b, 0xe1, 0xbe, 0xb8, 0xa6, 0x27, + 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x9e, 0xff, 0x6a, 0xc2, 0x04, 0x00, 0x00, +} + +func (m *State) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *State) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *State) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintState(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x7a + } + if len(m.LastResultsHash) > 0 { + i -= len(m.LastResultsHash) + copy(dAtA[i:], m.LastResultsHash) + i = encodeVarintState(dAtA, i, uint64(len(m.LastResultsHash))) + i-- + dAtA[i] = 0x72 + } + if m.LastHeightConsensusParamsChanged != 0 { + i = encodeVarintState(dAtA, i, uint64(m.LastHeightConsensusParamsChanged)) + i-- + dAtA[i] = 0x68 + } + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintState(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + if m.LastHeightValidatorsChanged != 0 { + i = encodeVarintState(dAtA, i, uint64(m.LastHeightValidatorsChanged)) + i-- + dAtA[i] = 0x58 + } + if m.LastValidators != nil { + { + size, err := m.LastValidators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintState(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + if m.Validators != nil { + { + size, err := m.Validators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintState(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + if m.NextValidators != nil { + { + size, err := m.NextValidators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintState(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + if m.DAHeight != 0 { + i = encodeVarintState(dAtA, i, uint64(m.DAHeight)) + i-- + dAtA[i] = 0x38 + } + n5, err5 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime):]) + if err5 != nil { + return 0, err5 + } + i -= n5 + i = encodeVarintState(dAtA, i, uint64(n5)) + i-- + dAtA[i] = 0x32 + { + size, err := m.LastBlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintState(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if m.LastBlockHeight != 0 { + i = encodeVarintState(dAtA, i, uint64(m.LastBlockHeight)) + i-- + dAtA[i] = 0x20 + } + if m.InitialHeight != 0 { + i = encodeVarintState(dAtA, i, uint64(m.InitialHeight)) + i-- + dAtA[i] = 0x18 + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintState(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0x12 + } + if m.Version != nil { + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintState(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintState(dAtA []byte, offset int, v uint64) int { + offset -= sovState(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *State) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Version != nil { + l = m.Version.Size() + n += 1 + l + sovState(uint64(l)) + } + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovState(uint64(l)) + } + if m.InitialHeight != 0 { + n += 1 + sovState(uint64(m.InitialHeight)) + } + if m.LastBlockHeight != 0 { + n += 1 + sovState(uint64(m.LastBlockHeight)) + } + l = m.LastBlockID.Size() + n += 1 + l + sovState(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime) + n += 1 + l + sovState(uint64(l)) + if m.DAHeight != 0 { + n += 1 + sovState(uint64(m.DAHeight)) + } + if m.NextValidators != nil { + l = m.NextValidators.Size() + n += 1 + l + sovState(uint64(l)) + } + if m.Validators != nil { + l = m.Validators.Size() + n += 1 + l + sovState(uint64(l)) + } + if m.LastValidators != nil { + l = m.LastValidators.Size() + n += 1 + l + sovState(uint64(l)) + } + if m.LastHeightValidatorsChanged != 0 { + n += 1 + sovState(uint64(m.LastHeightValidatorsChanged)) + } + l = m.ConsensusParams.Size() + n += 1 + l + sovState(uint64(l)) + if m.LastHeightConsensusParamsChanged != 0 { + n += 1 + sovState(uint64(m.LastHeightConsensusParamsChanged)) + } + l = len(m.LastResultsHash) + if l > 0 { + n += 1 + l + sovState(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovState(uint64(l)) + } + return n +} + +func sovState(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozState(x uint64) (n int) { + return sovState(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *State) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: State: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: State: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Version == nil { + m.Version = &state.Version{} + } + if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialHeight", wireType) + } + m.InitialHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockHeight", wireType) + } + m.LastBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastBlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastBlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.LastBlockTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DAHeight", wireType) + } + m.DAHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DAHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.NextValidators == nil { + m.NextValidators = &types.ValidatorSet{} + } + if err := m.NextValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Validators == nil { + m.Validators = &types.ValidatorSet{} + } + if err := m.Validators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastValidators == nil { + m.LastValidators = &types.ValidatorSet{} + } + if err := m.LastValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightValidatorsChanged", wireType) + } + m.LastHeightValidatorsChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightValidatorsChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightConsensusParamsChanged", wireType) + } + m.LastHeightConsensusParamsChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightConsensusParamsChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastResultsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastResultsHash = append(m.LastResultsHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastResultsHash == nil { + m.LastResultsHash = []byte{} + } + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowState + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthState + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthState + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipState(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthState + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipState(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowState + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowState + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowState + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthState + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupState + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthState + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthState = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowState = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupState = fmt.Errorf("proto: unexpected end of group") +) diff --git a/types/serialization.go b/types/serialization.go index ffd30e24485..845164bcc25 100644 --- a/types/serialization.go +++ b/types/serialization.go @@ -5,6 +5,7 @@ import ( pb "github.com/celestiaorg/optimint/types/pb/optimint" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/types" ) // MarshalBinary encodes Block into binary form and returns it. @@ -186,6 +187,71 @@ func (c *Commit) FromProto(other *pb.Commit) error { return nil } +func (s *State) ToProto() (*pb.State, error) { + nextValidators, err := s.NextValidators.ToProto() + if err != nil { + return nil, err + } + validators, err := s.Validators.ToProto() + if err != nil { + return nil, err + } + lastValidators, err := s.LastValidators.ToProto() + if err != nil { + return nil, err + } + + return &pb.State{ + Version: &s.Version, + ChainId: s.ChainID, + InitialHeight: s.InitialHeight, + LastBlockHeight: s.LastBlockHeight, + LastBlockID: s.LastBlockID.ToProto(), + LastBlockTime: s.LastBlockTime, + DAHeight: s.DAHeight, + NextValidators: nextValidators, + Validators: validators, + LastValidators: lastValidators, + LastHeightValidatorsChanged: s.LastHeightValidatorsChanged, + ConsensusParams: s.ConsensusParams, + LastHeightConsensusParamsChanged: s.LastHeightConsensusParamsChanged, + LastResultsHash: s.LastResultsHash[:], + AppHash: s.AppHash[:], + }, nil +} + +func (s *State) FromProto(other *pb.State) error { + var err error + s.Version = *other.Version + s.ChainID = other.ChainId + s.InitialHeight = other.InitialHeight + s.LastBlockHeight = other.LastBlockHeight + lastBlockID, err := types.BlockIDFromProto(&other.LastBlockID) + if err != nil { + return err + } + s.LastBlockID = *lastBlockID + s.LastBlockTime = other.LastBlockTime + s.DAHeight = other.DAHeight + s.NextValidators, err = types.ValidatorSetFromProto(other.NextValidators) + if err != nil { + return err + } + s.Validators, err = types.ValidatorSetFromProto(other.Validators) + if err != nil { + return err + } + s.LastValidators, err = types.ValidatorSetFromProto(other.LastValidators) + if err != nil { + return err + } + s.LastHeightValidatorsChanged = other.LastHeightValidatorsChanged + copy(s.LastResultsHash[:], other.LastResultsHash) + copy(s.AppHash[:], other.AppHash) + + return nil +} + func txsToByteSlices(txs Txs) [][]byte { bytes := make([][]byte, len(txs)) for i := range txs { diff --git a/state/state.go b/types/state.go similarity index 99% rename from state/state.go rename to types/state.go index 09850fae59b..92609673543 100644 --- a/state/state.go +++ b/types/state.go @@ -1,4 +1,4 @@ -package state +package types import ( "fmt"