diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d8617b6c42..33cb0a3f7e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -10,12 +10,11 @@ /api/ @Liuhaai @millken @CoderZhi /config/ @dustinxie @CoderZhi /p2p/ @Liuhaai @dustinxie - /action/ @CoderZhi @dustinxie /blockchain/ @CoderZhi @dustinxie /blockindex/ @CoderZhi @dustinxie /crypto/ @CoderZhi @dustinxie -/db/ @CoderZhi @dustinxie +/db/ @CoderZhi @dustinxie @Liuhaai /dispatcher/ @CoderZhi @dustinxie /pkg/ @dustinxie /server/ @CoderZhi @dustinxie diff --git a/api/grpcserver_integrity_test.go b/api/grpcserver_integrity_test.go index 949aa01956..7a56a45036 100644 --- a/api/grpcserver_integrity_test.go +++ b/api/grpcserver_integrity_test.go @@ -972,7 +972,7 @@ func TestGrpcServer_GetActionIntegrity(t *testing.T) { if !test.checkPending { blk, err := dao.GetBlockByHeight(test.blkNumber) require.NoError(err) - timeStamp := blk.ConvertToBlockHeaderPb().GetCore().GetTimestamp() + timeStamp := blk.Header.Proto().GetCore().GetTimestamp() _blkHash := blk.HashBlock() require.Equal(hex.EncodeToString(_blkHash[:]), act.BlkHash) require.Equal(test.blkNumber, act.BlkHeight) diff --git a/blockchain/block/block.go b/blockchain/block/block.go index e9d0e4c8cc..17f0d5fc6e 100644 --- a/blockchain/block/block.go +++ b/blockchain/block/block.go @@ -28,11 +28,6 @@ type Block struct { Receipts []*action.Receipt } -// ConvertToBlockHeaderPb converts BlockHeader to BlockHeader -func (b *Block) ConvertToBlockHeaderPb() *iotextypes.BlockHeader { - return b.Header.BlockHeaderProto() -} - // ConvertToBlockPb converts Block to Block func (b *Block) ConvertToBlockPb() *iotextypes.Block { footer, err := b.ConvertToBlockFooterPb() @@ -40,7 +35,7 @@ func (b *Block) ConvertToBlockPb() *iotextypes.Block { log.L().Panic("failed to convert block footer to protobuf message") } return &iotextypes.Block{ - Header: b.ConvertToBlockHeaderPb(), + Header: b.Header.Proto(), Body: b.Body.Proto(), Footer: footer, } diff --git a/blockchain/block/header.go b/blockchain/block/header.go index a79723d9a3..4301f53ac8 100644 --- a/blockchain/block/header.go +++ b/blockchain/block/header.go @@ -73,8 +73,8 @@ func (h *Header) HashBlock() hash.Hash256 { return h.HashHeader() } // LogsBloomfilter return the bloom filter for all contract log events func (h *Header) LogsBloomfilter() bloom.BloomFilter { return h.logsBloom } -// BlockHeaderProto returns BlockHeader proto. -func (h *Header) BlockHeaderProto() *iotextypes.BlockHeader { +// Proto returns BlockHeader proto. +func (h *Header) Proto() *iotextypes.BlockHeader { header := iotextypes.BlockHeader{ Core: h.BlockHeaderCoreProto(), } @@ -152,7 +152,7 @@ func (h *Header) SerializeCore() []byte { // Serialize returns the serialized byte stream of the block header func (h *Header) Serialize() ([]byte, error) { - return proto.Marshal(h.BlockHeaderProto()) + return proto.Marshal(h.Proto()) } // Deserialize loads from the serialized byte stream diff --git a/blockchain/block/header_test.go b/blockchain/block/header_test.go index 2107dfe19a..6e81f86926 100644 --- a/blockchain/block/header_test.go +++ b/blockchain/block/header_test.go @@ -31,7 +31,7 @@ func TestHeader(t *testing.T) { require.Equal("04755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf33", header.PublicKey().HexString()) require.True(isEqual(expected, header.ReceiptRoot())) require.True(isEqual("39f9a57253c8396601394ca504ff0cd648adefbd1d0728e9e77fd211e34c5258", header.HashBlock())) - require.NotNil(header.BlockHeaderProto()) + require.NotNil(header.Proto()) require.NotNil(header.BlockHeaderCoreProto()) require.Equal("io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", header.ProducerAddress()) } @@ -55,7 +55,7 @@ func TestSerDesHeadrer(t *testing.T) { require.Equal("04755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf33", header.PublicKey().HexString()) require.True(isEqual(expected, header.ReceiptRoot())) require.True(isEqual("39f9a57253c8396601394ca504ff0cd648adefbd1d0728e9e77fd211e34c5258", header.HashBlock())) - require.NotNil(header.BlockHeaderProto()) + require.NotNil(header.Proto()) require.NotNil(header.BlockHeaderCoreProto()) require.Equal("io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", header.ProducerAddress()) } diff --git a/blockchain/genesis/genesis.go b/blockchain/genesis/genesis.go index 325a616b6f..e4ed1c662e 100644 --- a/blockchain/genesis/genesis.go +++ b/blockchain/genesis/genesis.go @@ -36,7 +36,7 @@ var ( ) func init() { - initTestDefaultConfig() + initTestDefaultConfig(&Default) } func defaultConfig() Genesis { @@ -113,15 +113,21 @@ func defaultConfig() Genesis { } } -func initTestDefaultConfig() { - Default = defaultConfig() - Default.PacificBlockHeight = 0 +// TestDefault is the default genesis config for testing +func TestDefault() Genesis { + ge := defaultConfig() + initTestDefaultConfig(&ge) + return ge +} + +func initTestDefaultConfig(cfg *Genesis) { + cfg.PacificBlockHeight = 0 for i := 0; i < identityset.Size(); i++ { addr := identityset.Address(i).String() value := unit.ConvertIotxToRau(100000000).String() - Default.InitBalanceMap[addr] = value - if uint64(i) < Default.NumDelegates { - Default.Delegates = append(Default.Delegates, Delegate{ + cfg.InitBalanceMap[addr] = value + if uint64(i) < cfg.NumDelegates { + cfg.Delegates = append(cfg.Delegates, Delegate{ OperatorAddrStr: addr, RewardAddrStr: addr, VotesStr: value, diff --git a/db/batch/writeinfo.go b/db/batch/writeinfo.go index 3c96820b2c..0717f25b54 100644 --- a/db/batch/writeinfo.go +++ b/db/batch/writeinfo.go @@ -85,18 +85,21 @@ func (wi *WriteInfo) Error() string { // Serialize serializes the write info func (wi *WriteInfo) Serialize() []byte { - bytes := []byte{byte(wi.writeType)} - bytes = append(bytes, []byte(wi.namespace)...) - bytes = append(bytes, wi.key...) - bytes = append(bytes, wi.value...) + lenNamespace, lenKey, lenValue := len(wi.namespace), len(wi.key), len(wi.value) + bytes := make([]byte, 1+lenNamespace+lenKey+lenValue) + bytes[0] = byte(wi.writeType) + copy(bytes[1:], []byte(wi.namespace)) + copy(bytes[1+lenNamespace:], wi.key) + copy(bytes[1+lenNamespace+lenKey:], wi.value) return bytes } // SerializeWithoutWriteType serializes the write info without write type func (wi *WriteInfo) SerializeWithoutWriteType() []byte { - bytes := make([]byte, 0) - bytes = append(bytes, []byte(wi.namespace)...) - bytes = append(bytes, wi.key...) - bytes = append(bytes, wi.value...) + lenNamespace, lenKey, lenValue := len(wi.namespace), len(wi.key), len(wi.value) + bytes := make([]byte, lenNamespace+lenKey+lenValue) + copy(bytes[0:], []byte(wi.namespace)) + copy(bytes[lenNamespace:], wi.key) + copy(bytes[lenNamespace+lenKey:], wi.value) return bytes } diff --git a/state/factory/factory_test.go b/state/factory/factory_test.go index 49687008aa..b97c453df3 100644 --- a/state/factory/factory_test.go +++ b/state/factory/factory_test.go @@ -959,14 +959,15 @@ func TestSTXRunActions(t *testing.T) { cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100" cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "200" + registry := protocol.NewRegistry() + acc := account.NewProtocol(rewarding.DepositGas) + require.NoError(acc.Register(registry)) + db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize) require.NoError(err) - sdb, err := NewStateDB(cfg, db2, SkipBlockValidationStateDBOption()) + sdb, err := NewStateDB(cfg, db2, SkipBlockValidationStateDBOption(), RegistryStateDBOption(registry)) require.NoError(err) - registry := protocol.NewRegistry() - acc := account.NewProtocol(rewarding.DepositGas) - require.NoError(acc.Register(registry)) ctx := protocol.WithBlockCtx( genesis.WithGenesisContext(context.Background(), cfg.Genesis), protocol.BlockCtx{}, @@ -1383,7 +1384,7 @@ func TestStateDBPatch(t *testing.T) { SignAndBuild(identityset.PrivateKey(27)) require.NoError(err) require.NoError(sdb.PutBlock(ctx, &blk2)) - v11, err = trieDB.Get(n1, ha1) + _, err = trieDB.Get(n1, ha1) require.EqualError(errors.Cause(err), db.ErrNotExist.Error()) v12, err = trieDB.Get(n1, ha2) require.NoError(err) diff --git a/state/factory/workingset.go b/state/factory/workingset.go index 1d46618bd1..e1edc07091 100644 --- a/state/factory/workingset.go +++ b/state/factory/workingset.go @@ -167,23 +167,21 @@ func (ws *workingSet) runAction( return nil, errors.Wrapf(err, "Failed to get hash") } var receipt *action.Receipt + defer ws.ResetSnapshots() for _, actionHandler := range reg.All() { receipt, err = actionHandler.Handle(ctx, elp.Action(), ws) if err != nil { - err = errors.Wrapf( + return nil, errors.Wrapf( err, "error when action %x mutates states", elpHash, ) } - if receipt != nil || err != nil { - break + if receipt != nil { + return receipt, nil } } - ws.ResetSnapshots() - - // TODO (zhi): return error if both receipt and err are nil - return receipt, err + return nil, errors.New("receipt is nil") } func validateChainID(ctx context.Context, chainID uint32) error { diff --git a/state/factory/workingset_test.go b/state/factory/workingset_test.go index 0f9445446e..56b8d5ae33 100644 --- a/state/factory/workingset_test.go +++ b/state/factory/workingset_test.go @@ -7,7 +7,7 @@ package factory import ( "context" - "math/rand" + "math/big" "testing" "time" @@ -17,10 +17,12 @@ import ( "github.com/iotexproject/iotex-core/action" "github.com/iotexproject/iotex-core/action/protocol" + "github.com/iotexproject/iotex-core/action/protocol/account" + "github.com/iotexproject/iotex-core/action/protocol/rewarding" + "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/db" - "github.com/iotexproject/iotex-core/pkg/unit" "github.com/iotexproject/iotex-core/state" "github.com/iotexproject/iotex-core/test/identityset" "github.com/iotexproject/iotex-core/testutil" @@ -183,40 +185,65 @@ func TestWorkingSet_Dock(t *testing.T) { } func TestWorkingSet_ValidateBlock(t *testing.T) { + require := require.New(t) + registry := protocol.NewRegistry() + require.NoError(account.NewProtocol(rewarding.DepositGas).Register(registry)) + cfg := Config{ + Chain: blockchain.DefaultConfig, + Genesis: genesis.TestDefault(), + } + cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100000000" var ( - require = require.New(t) - f1, _ = NewFactory(DefaultConfig, db.NewMemKVStore()) - f2, _ = NewStateDB(DefaultConfig, db.NewMemKVStore()) + f1, _ = NewFactory(cfg, db.NewMemKVStore(), RegistryOption(registry)) + f2, _ = NewStateDB(cfg, db.NewMemKVStore(), RegistryStateDBOption(registry)) factories = []Factory{f1, f2} - digestHash = hash.Hash256b([]byte{65, 99, 99, 111, 117, 110, 116, 99, 117, 114, 114, - 101, 110, 116, 72, 101, 105, 103, 104, 116, 1, 0, 0, 0, 0, 0, 0, 0}) + digestHash = hash.BytesToHash256([]byte{67, 246, 156, 149, 78, 160, 19, 137, 23, 214, 154, + 1, 247, 186, 71, 218, 116, 201, 156, 178, 198, 34, 159, 89, 105, 167, 240, 191, + 83, 239, 183, 117}) + receiptRoot = hash.BytesToHash256([]byte{43, 195, 20, 81, 149, 72, 181, 0, 230, 212, 137, + 96, 64, 59, 99, 229, 48, 189, 105, 53, 69, 94, 195, 36, 128, 228, 210, 211, 189, + 116, 62, 176}) tests = []struct { block *block.Block err error }{ - {makeBlock(t, 1, hash.ZeroHash256, digestHash), nil}, { - makeBlock(t, 3, hash.ZeroHash256, digestHash), + makeBlock(t, 1, hash.ZeroHash256, receiptRoot, digestHash), + nil, + }, + { + makeBlock(t, 3, hash.ZeroHash256, receiptRoot, digestHash), action.ErrNonceTooHigh, }, { - makeBlock(t, 1, hash.Hash256b([]byte("test")), digestHash), + makeBlock(t, 1, hash.ZeroHash256, hash.Hash256b([]byte("test")), digestHash), block.ErrReceiptRootMismatch, }, { - makeBlock(t, 1, hash.ZeroHash256, hash.Hash256b([]byte("test"))), + makeBlock(t, 1, hash.ZeroHash256, receiptRoot, hash.Hash256b([]byte("test"))), block.ErrDeltaStateMismatch, }, } ) - gasLimit := testutil.TestGasLimit * 100000 + + ctx := protocol.WithBlockCtx( + genesis.WithGenesisContext(context.Background(), cfg.Genesis), + protocol.BlockCtx{}, + ) + require.NoError(f1.Start(ctx)) + require.NoError(f2.Start(ctx)) + defer func() { + require.NoError(f1.Stop(ctx)) + require.NoError(f2.Stop(ctx)) + }() + zctx := protocol.WithBlockCtx(context.Background(), protocol.BlockCtx{ BlockHeight: uint64(1), Producer: identityset.Address(27), - GasLimit: gasLimit, + GasLimit: testutil.TestGasLimit * 100000, }) - zctx = genesis.WithGenesisContext(zctx, genesis.Default) + zctx = genesis.WithGenesisContext(zctx, cfg.Genesis) zctx = protocol.WithFeatureCtx(protocol.WithBlockchainCtx(zctx, protocol.BlockchainCtx{ ChainID: 1, })) @@ -227,17 +254,15 @@ func TestWorkingSet_ValidateBlock(t *testing.T) { } } -func makeBlock(t *testing.T, nonce uint64, rootHash hash.Hash256, digest hash.Hash256) *block.Block { - rand.Seed(time.Now().Unix()) +func makeBlock(t *testing.T, nonce uint64, prevHash hash.Hash256, receiptRoot hash.Hash256, digest hash.Hash256) *block.Block { var sevlps []action.SealedEnvelope - r := rand.Int() tsf, err := action.NewTransfer( - uint64(r), - unit.ConvertIotxToRau(1000+int64(r)), - identityset.Address(r%identityset.Size()).String(), + uint64(nonce), + big.NewInt(1), + identityset.Address(29).String(), nil, - 20000+uint64(r), - unit.ConvertIotxToRau(1+int64(r)), + testutil.TestGasLimit, + big.NewInt(0), ) require.NoError(t, err) eb := action.EnvelopeBuilder{} @@ -248,7 +273,7 @@ func makeBlock(t *testing.T, nonce uint64, rootHash hash.Hash256, digest hash.Ha SetNonce(nonce). SetVersion(1). Build() - sevlp, err := action.Sign(evlp, identityset.PrivateKey((r+1)%identityset.Size())) + sevlp, err := action.Sign(evlp, identityset.PrivateKey(28)) require.NoError(t, err) sevlps = append(sevlps, sevlp) rap := block.RunnableActionsBuilder{} @@ -257,9 +282,9 @@ func makeBlock(t *testing.T, nonce uint64, rootHash hash.Hash256, digest hash.Ha SetHeight(1). SetTimestamp(time.Now()). SetVersion(1). - SetReceiptRoot(rootHash). + SetReceiptRoot(receiptRoot). SetDeltaStateDigest(digest). - SetPrevBlockHash(hash.Hash256b([]byte("test"))). + SetPrevBlockHash(prevHash). SignAndBuild(identityset.PrivateKey(0)) require.NoError(t, err) return &blk