github.com/iotexproject/iotex-core@v1.14.1-rc1/state/factory/factory_test.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package factory
     7  
     8  import (
     9  	"context"
    10  	"encoding/csv"
    11  	"encoding/hex"
    12  	"math/big"
    13  	"math/rand"
    14  	"os"
    15  	"path/filepath"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/golang/mock/gomock"
    20  	"github.com/pkg/errors"
    21  	"github.com/stretchr/testify/require"
    22  
    23  	"github.com/iotexproject/go-pkgs/crypto"
    24  	"github.com/iotexproject/go-pkgs/hash"
    25  	"github.com/iotexproject/iotex-address/address"
    26  	"github.com/iotexproject/iotex-election/test/mock/mock_committee"
    27  	"github.com/iotexproject/iotex-election/types"
    28  
    29  	"github.com/iotexproject/iotex-core/action"
    30  	"github.com/iotexproject/iotex-core/action/protocol"
    31  	"github.com/iotexproject/iotex-core/action/protocol/account"
    32  	accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util"
    33  	"github.com/iotexproject/iotex-core/action/protocol/execution/evm"
    34  	"github.com/iotexproject/iotex-core/action/protocol/poll"
    35  	"github.com/iotexproject/iotex-core/action/protocol/rewarding"
    36  	"github.com/iotexproject/iotex-core/action/protocol/rolldpos"
    37  	"github.com/iotexproject/iotex-core/action/protocol/vote/candidatesutil"
    38  	"github.com/iotexproject/iotex-core/blockchain"
    39  	"github.com/iotexproject/iotex-core/blockchain/block"
    40  	"github.com/iotexproject/iotex-core/blockchain/genesis"
    41  	"github.com/iotexproject/iotex-core/db"
    42  	"github.com/iotexproject/iotex-core/pkg/enc"
    43  	"github.com/iotexproject/iotex-core/pkg/util/fileutil"
    44  	"github.com/iotexproject/iotex-core/state"
    45  	"github.com/iotexproject/iotex-core/test/identityset"
    46  	"github.com/iotexproject/iotex-core/test/mock/mock_actpool"
    47  	"github.com/iotexproject/iotex-core/testutil"
    48  )
    49  
    50  const (
    51  	_triePath    = "trie.test"
    52  	_stateDBPath = "stateDB.test"
    53  )
    54  
    55  var _letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    56  
    57  func randStringRunes(n int) string {
    58  	b := make([]rune, n)
    59  	for i := range b {
    60  		b[i] = _letterRunes[rand.Intn(len(_letterRunes))]
    61  	}
    62  	return string(b)
    63  }
    64  
    65  func TestGenerateConfig(t *testing.T) {
    66  	require := require.New(t)
    67  	cfg := GenerateConfig(blockchain.DefaultConfig, genesis.Default)
    68  	require.Equal(27, len(cfg.Genesis.InitBalanceMap))
    69  	require.Equal(blockchain.DefaultConfig.ChainDBPath, cfg.Chain.ChainDBPath)
    70  }
    71  
    72  func TestSnapshot(t *testing.T) {
    73  	require := require.New(t)
    74  	testTriePath, err := testutil.PathOfTempFile(_triePath)
    75  	require.NoError(err)
    76  
    77  	cfg := DefaultConfig
    78  	db1, err := db.CreateKVStore(db.DefaultConfig, testTriePath)
    79  	require.NoError(err)
    80  
    81  	cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "5"
    82  	cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "7"
    83  	registry := protocol.NewRegistry()
    84  	sf, err := NewFactory(cfg, db1, RegistryOption(registry))
    85  	require.NoError(err)
    86  	acc := account.NewProtocol(rewarding.DepositGas)
    87  	require.NoError(acc.Register(registry))
    88  	ctx := protocol.WithBlockCtx(
    89  		genesis.WithGenesisContext(context.Background(), cfg.Genesis),
    90  		protocol.BlockCtx{},
    91  	)
    92  	require.NoError(sf.Start(ctx))
    93  	defer func() {
    94  		require.NoError(sf.Stop(ctx))
    95  		testutil.CleanupPath(testTriePath)
    96  	}()
    97  	ws, err := sf.(workingSetCreator).newWorkingSet(ctx, 1)
    98  	require.NoError(err)
    99  	testSnapshot(ws, t)
   100  	testRevert(ws, t)
   101  }
   102  
   103  func TestSDBSnapshot(t *testing.T) {
   104  	require := require.New(t)
   105  	testStateDBPath, err := testutil.PathOfTempFile(_stateDBPath)
   106  	require.NoError(err)
   107  	defer testutil.CleanupPath(testStateDBPath)
   108  
   109  	cfg := DefaultConfig
   110  	cfg.Chain.TrieDBPatchFile = ""
   111  	cfg.Chain.TrieDBPath = testStateDBPath
   112  	cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "5"
   113  	cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "7"
   114  	registry := protocol.NewRegistry()
   115  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   116  	require.NoError(err)
   117  	sdb, err := NewStateDB(cfg, db2, RegistryStateDBOption(registry))
   118  	require.NoError(err)
   119  	acc := account.NewProtocol(rewarding.DepositGas)
   120  	require.NoError(acc.Register(registry))
   121  	ctx := protocol.WithBlockCtx(
   122  		genesis.WithGenesisContext(context.Background(), cfg.Genesis),
   123  		protocol.BlockCtx{},
   124  	)
   125  	require.NoError(sdb.Start(ctx))
   126  	height, err := sdb.Height()
   127  	require.NoError(err)
   128  	ws, err := sdb.(workingSetCreator).newWorkingSet(ctx, height)
   129  	require.NoError(err)
   130  	testSnapshot(ws, t)
   131  	testSDBRevert(ws, t)
   132  }
   133  
   134  func testRevert(ws *workingSet, t *testing.T) {
   135  	require := require.New(t)
   136  	sHash := hash.BytesToHash160(identityset.Address(28).Bytes())
   137  
   138  	s, err := accountutil.LoadAccount(ws, identityset.Address(28))
   139  	require.NoError(err)
   140  	require.Equal(big.NewInt(5), s.Balance)
   141  	s0 := ws.Snapshot()
   142  	require.Equal(1, s0)
   143  
   144  	require.NoError(s.AddBalance(big.NewInt(5)))
   145  	require.Equal(big.NewInt(10), s.Balance)
   146  	_, err = ws.PutState(s, protocol.LegacyKeyOption(sHash))
   147  	require.NoError(err)
   148  
   149  	require.NoError(ws.Revert(s0))
   150  	_, err = ws.State(s, protocol.LegacyKeyOption(sHash))
   151  	require.NoError(err)
   152  	require.Equal(big.NewInt(5), s.Balance)
   153  }
   154  
   155  func testSDBRevert(ws *workingSet, t *testing.T) {
   156  	require := require.New(t)
   157  	sHash := hash.BytesToHash160(identityset.Address(28).Bytes())
   158  
   159  	s, err := accountutil.LoadAccount(ws, identityset.Address(28))
   160  	require.NoError(err)
   161  	require.Equal(big.NewInt(5), s.Balance)
   162  	s0 := ws.Snapshot()
   163  	require.Equal(1, s0)
   164  
   165  	require.NoError(s.AddBalance(big.NewInt(5)))
   166  	require.Equal(big.NewInt(10), s.Balance)
   167  	_, err = ws.PutState(s, protocol.LegacyKeyOption(sHash))
   168  	require.NoError(err)
   169  
   170  	require.NoError(ws.Revert(s0))
   171  	_, err = ws.State(s, protocol.LegacyKeyOption(sHash))
   172  	require.NoError(err)
   173  	require.Equal(big.NewInt(5), s.Balance)
   174  }
   175  
   176  func testSnapshot(ws *workingSet, t *testing.T) {
   177  	require := require.New(t)
   178  	sHash := hash.BytesToHash160(identityset.Address(28).Bytes())
   179  	sHashAddr := identityset.Address(28)
   180  	tHash := hash.BytesToHash160(identityset.Address(29).Bytes())
   181  	tHashAddr := identityset.Address(29)
   182  
   183  	s, err := accountutil.LoadAccount(ws, tHashAddr)
   184  	require.NoError(err)
   185  	require.Equal(big.NewInt(7), s.Balance)
   186  	s, err = accountutil.LoadAccount(ws, sHashAddr)
   187  	require.NoError(err)
   188  	require.Equal(big.NewInt(5), s.Balance)
   189  	s0 := ws.Snapshot()
   190  	require.Zero(s0)
   191  	require.NoError(s.AddBalance(big.NewInt(5)))
   192  	require.Equal(big.NewInt(10), s.Balance)
   193  	_, err = ws.PutState(s, protocol.LegacyKeyOption(sHash))
   194  	require.NoError(err)
   195  	s1 := ws.Snapshot()
   196  	require.Equal(1, s1)
   197  	require.NoError(s.AddBalance(big.NewInt(5)))
   198  	require.Equal(big.NewInt(15), s.Balance)
   199  	_, err = ws.PutState(s, protocol.LegacyKeyOption(sHash))
   200  	require.NoError(err)
   201  
   202  	s, err = accountutil.LoadAccount(ws, tHashAddr)
   203  	require.NoError(err)
   204  	require.Equal(big.NewInt(7), s.Balance)
   205  	s2 := ws.Snapshot()
   206  	require.Equal(2, s2)
   207  	require.NoError(s.AddBalance(big.NewInt(6)))
   208  	require.Equal(big.NewInt(13), s.Balance)
   209  	_, err = ws.PutState(s, protocol.LegacyKeyOption(tHash))
   210  	require.NoError(err)
   211  
   212  	require.NoError(ws.Revert(s2))
   213  	_, err = ws.State(s, protocol.LegacyKeyOption(sHash))
   214  	require.NoError(err)
   215  	require.Equal(big.NewInt(15), s.Balance)
   216  	_, err = ws.State(s, protocol.LegacyKeyOption(tHash))
   217  	require.NoError(err)
   218  	require.Equal(big.NewInt(7), s.Balance)
   219  	require.NoError(ws.Revert(s1))
   220  	_, err = ws.State(s, protocol.LegacyKeyOption(sHash))
   221  	require.NoError(err)
   222  	require.Equal(big.NewInt(10), s.Balance)
   223  	require.NoError(ws.Revert(s0))
   224  	_, err = ws.State(s, protocol.LegacyKeyOption(sHash))
   225  	require.NoError(err)
   226  	require.Equal(big.NewInt(5), s.Balance)
   227  }
   228  
   229  func TestCandidates(t *testing.T) {
   230  	cfg := DefaultConfig
   231  	sf, err := NewFactory(cfg, db.NewMemKVStore(), SkipBlockValidationOption())
   232  	require.NoError(t, err)
   233  	testCandidates(sf, t)
   234  }
   235  
   236  func TestSDBCandidates(t *testing.T) {
   237  	cfg := DefaultConfig
   238  	sdb, err := NewStateDB(cfg, db.NewMemKVStore(), SkipBlockValidationStateDBOption())
   239  	require.NoError(t, err)
   240  	testCandidates(sdb, t)
   241  }
   242  
   243  func testCandidates(sf Factory, t *testing.T) {
   244  	sc := state.CandidateList{}
   245  	result := types.NewElectionResultForTest(time.Now())
   246  	for _, c := range result.Delegates() {
   247  		oa, err := address.FromString(string(c.OperatorAddress()))
   248  		require.NoError(t, err)
   249  		ra, err := address.FromString(string(c.RewardAddress()))
   250  		require.NoError(t, err)
   251  		sc = append(sc, &state.Candidate{
   252  			Address:       oa.String(),
   253  			Votes:         c.Score(),
   254  			RewardAddress: ra.String(),
   255  			CanName:       c.Name(),
   256  		})
   257  	}
   258  	act := action.NewPutPollResult(1, 1, sc)
   259  	bd := &action.EnvelopeBuilder{}
   260  	elp := bd.SetGasLimit(uint64(100000)).
   261  		SetGasPrice(big.NewInt(10)).
   262  		SetAction(act).Build()
   263  	selp, err := action.Sign(elp, identityset.PrivateKey(27))
   264  	require.NoError(t, err)
   265  	require.NotNil(t, selp)
   266  
   267  	ctrl := gomock.NewController(t)
   268  
   269  	committee := mock_committee.NewMockCommittee(ctrl)
   270  	committee.EXPECT().ResultByHeight(uint64(123456)).Return(result, nil).AnyTimes()
   271  	committee.EXPECT().HeightByTime(gomock.Any()).Return(uint64(123456), nil).AnyTimes()
   272  
   273  	require.NoError(t, sf.Register(rolldpos.NewProtocol(36, 36, 20)))
   274  	cfg := DefaultConfig
   275  	slasher, err := poll.NewSlasher(
   276  		func(uint64, uint64) (map[string]uint64, error) {
   277  			return nil, nil
   278  		},
   279  		nil,
   280  		nil,
   281  		nil,
   282  		nil,
   283  		cfg.Genesis.NumCandidateDelegates,
   284  		cfg.Genesis.NumDelegates,
   285  		cfg.Genesis.DardanellesNumSubEpochs,
   286  		cfg.Genesis.ProductivityThreshold,
   287  		cfg.Genesis.ProbationEpochPeriod,
   288  		cfg.Genesis.UnproductiveDelegateMaxCacheSize,
   289  		cfg.Genesis.ProbationIntensityRate)
   290  	require.NoError(t, err)
   291  	p, err := poll.NewGovernanceChainCommitteeProtocol(
   292  		nil,
   293  		committee,
   294  		uint64(123456),
   295  		func(uint64) (time.Time, error) { return time.Now(), nil },
   296  		cfg.Chain.PollInitialCandidatesInterval,
   297  		slasher,
   298  	)
   299  	require.NoError(t, err)
   300  	require.NoError(t, sf.Register(p))
   301  	gasLimit := testutil.TestGasLimit
   302  
   303  	// TODO: investigate why registry cannot be added in the Blockchain Ctx
   304  	ctx := protocol.WithBlockCtx(
   305  		genesis.WithGenesisContext(context.Background(), cfg.Genesis),
   306  		protocol.BlockCtx{
   307  			BlockHeight: 0,
   308  			Producer:    identityset.Address(27),
   309  			GasLimit:    gasLimit,
   310  		},
   311  	)
   312  	ctx = protocol.WithFeatureCtx(protocol.WithFeatureWithHeightCtx(ctx))
   313  	require.NoError(t, sf.Start(ctx))
   314  	defer require.NoError(t, sf.Stop(ctx))
   315  
   316  	blk, err := block.NewTestingBuilder().
   317  		SetHeight(1).
   318  		SetPrevBlockHash(hash.ZeroHash256).
   319  		SetTimeStamp(testutil.TimestampNow()).
   320  		AddActions([]*action.SealedEnvelope{selp}...).
   321  		SignAndBuild(identityset.PrivateKey(27))
   322  	require.NoError(t, err)
   323  	require.NoError(t, sf.PutBlock(
   324  		protocol.WithFeatureCtx(protocol.WithFeatureWithHeightCtx(
   325  			protocol.WithBlockchainCtx(
   326  				protocol.WithBlockCtx(
   327  					genesis.WithGenesisContext(context.Background(), cfg.Genesis),
   328  					protocol.BlockCtx{
   329  						BlockHeight: 1,
   330  						Producer:    identityset.Address(27),
   331  						GasLimit:    gasLimit,
   332  					},
   333  				),
   334  				protocol.BlockchainCtx{
   335  					ChainID: 1,
   336  				},
   337  			),
   338  		),
   339  		), &blk))
   340  
   341  	candidates, _, err := candidatesutil.CandidatesFromDB(sf, 1, true, false)
   342  	require.NoError(t, err)
   343  	require.Equal(t, len(sc), len(candidates))
   344  	for i, c := range candidates {
   345  		require.True(t, c.Equal(sc[i]))
   346  	}
   347  }
   348  
   349  func TestState(t *testing.T) {
   350  	testTriePath, err := testutil.PathOfTempFile(_triePath)
   351  	require.NoError(t, err)
   352  	defer testutil.CleanupPath(testTriePath)
   353  
   354  	cfg := DefaultConfig
   355  	db1, err := db.CreateKVStore(db.DefaultConfig, testTriePath)
   356  	require.NoError(t, err)
   357  	sf, err := NewFactory(cfg, db1, SkipBlockValidationOption())
   358  	require.NoError(t, err)
   359  	testState(sf, t)
   360  }
   361  
   362  func TestHistoryState(t *testing.T) {
   363  	r := require.New(t)
   364  	var err error
   365  	// using factory and enable history
   366  	cfg := DefaultConfig
   367  	cfg.Chain.TrieDBPath, err = testutil.PathOfTempFile(_triePath)
   368  	r.NoError(err)
   369  	cfg.Chain.EnableArchiveMode = true
   370  	db1, err := db.CreateKVStore(db.DefaultConfig, cfg.Chain.TrieDBPath)
   371  	r.NoError(err)
   372  	sf, err := NewFactory(cfg, db1, SkipBlockValidationOption())
   373  	r.NoError(err)
   374  	testHistoryState(sf, t, false, cfg.Chain.EnableArchiveMode)
   375  
   376  	// using stateDB and enable history
   377  	cfg.Chain.TrieDBPath, err = testutil.PathOfTempFile(_triePath)
   378  	r.NoError(err)
   379  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   380  	r.NoError(err)
   381  	sf, err = NewStateDB(cfg, db2, SkipBlockValidationStateDBOption())
   382  	r.NoError(err)
   383  	testHistoryState(sf, t, true, cfg.Chain.EnableArchiveMode)
   384  
   385  	// using factory and disable history
   386  	cfg.Chain.TrieDBPath, err = testutil.PathOfTempFile(_triePath)
   387  	r.NoError(err)
   388  	cfg.Chain.EnableArchiveMode = false
   389  	db1, err = db.CreateKVStore(db.DefaultConfig, cfg.Chain.TrieDBPath)
   390  	r.NoError(err)
   391  	sf, err = NewFactory(cfg, db1, SkipBlockValidationOption())
   392  	r.NoError(err)
   393  	testHistoryState(sf, t, false, cfg.Chain.EnableArchiveMode)
   394  
   395  	// using stateDB and disable history
   396  	cfg.Chain.TrieDBPath, err = testutil.PathOfTempFile(_triePath)
   397  	r.NoError(err)
   398  	db2, err = db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   399  	r.NoError(err)
   400  	sf, err = NewStateDB(cfg, db2, SkipBlockValidationStateDBOption())
   401  	r.NoError(err)
   402  	testHistoryState(sf, t, true, cfg.Chain.EnableArchiveMode)
   403  	defer func() {
   404  		testutil.CleanupPath(cfg.Chain.TrieDBPath)
   405  	}()
   406  }
   407  
   408  func TestFactoryStates(t *testing.T) {
   409  	r := require.New(t)
   410  	var err error
   411  	cfg := DefaultConfig
   412  	// using factory
   413  	cfg.Chain.TrieDBPath, err = testutil.PathOfTempFile(_triePath)
   414  	r.NoError(err)
   415  	db1, err := db.CreateKVStore(db.DefaultConfig, cfg.Chain.TrieDBPath)
   416  	r.NoError(err)
   417  	sf, err := NewFactory(cfg, db1, SkipBlockValidationOption())
   418  	r.NoError(err)
   419  	testFactoryStates(sf, t)
   420  
   421  	// using stateDB
   422  	cfg.Chain.TrieDBPath, err = testutil.PathOfTempFile(_triePath)
   423  	r.NoError(err)
   424  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   425  	r.NoError(err)
   426  	sf, err = NewStateDB(cfg, db2, SkipBlockValidationStateDBOption())
   427  	r.NoError(err)
   428  	testFactoryStates(sf, t)
   429  	defer testutil.CleanupPath(cfg.Chain.TrieDBPath)
   430  }
   431  
   432  func TestSDBState(t *testing.T) {
   433  	testDBPath, err := testutil.PathOfTempFile(_stateDBPath)
   434  	require.NoError(t, err)
   435  	defer testutil.CleanupPath(testDBPath)
   436  
   437  	cfg := DefaultConfig
   438  	cfg.Chain.TrieDBPath = testDBPath
   439  	db1, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   440  	require.NoError(t, err)
   441  	sdb, err := NewStateDB(cfg, db1, SkipBlockValidationStateDBOption())
   442  	require.NoError(t, err)
   443  	testState(sdb, t)
   444  }
   445  
   446  func testState(sf Factory, t *testing.T) {
   447  	// Create a dummy iotex address
   448  	a := identityset.Address(28)
   449  	priKeyA := identityset.PrivateKey(28)
   450  	acc := account.NewProtocol(rewarding.DepositGas)
   451  	require.NoError(t, sf.Register(acc))
   452  	ge := genesis.Default
   453  	ge.InitBalanceMap[a.String()] = "100"
   454  	gasLimit := uint64(1000000)
   455  	ctx := protocol.WithBlockchainCtx(protocol.WithBlockCtx(
   456  		context.Background(),
   457  		protocol.BlockCtx{
   458  			BlockHeight: 0,
   459  			Producer:    identityset.Address(27),
   460  			GasLimit:    gasLimit,
   461  		},
   462  	), protocol.BlockchainCtx{
   463  		ChainID: 1,
   464  	})
   465  	ctx = genesis.WithGenesisContext(ctx, ge)
   466  
   467  	require.NoError(t, sf.Start(ctx))
   468  	defer func() {
   469  		require.NoError(t, sf.Stop(ctx))
   470  	}()
   471  
   472  	tsf, err := action.NewTransfer(1, big.NewInt(10), identityset.Address(31).String(), nil, uint64(20000), big.NewInt(0))
   473  	require.NoError(t, err)
   474  	bd := &action.EnvelopeBuilder{}
   475  	elp := bd.SetAction(tsf).SetGasLimit(20000).SetNonce(1).Build()
   476  	selp, err := action.Sign(elp, priKeyA)
   477  	require.NoError(t, err)
   478  	ctx = protocol.WithBlockCtx(
   479  		ctx,
   480  		protocol.BlockCtx{
   481  			BlockHeight: 1,
   482  			Producer:    identityset.Address(27),
   483  			GasLimit:    gasLimit,
   484  		},
   485  	)
   486  	blk, err := block.NewTestingBuilder().
   487  		SetHeight(1).
   488  		SetPrevBlockHash(hash.ZeroHash256).
   489  		SetTimeStamp(testutil.TimestampNow()).
   490  		AddActions([]*action.SealedEnvelope{selp}...).
   491  		SignAndBuild(identityset.PrivateKey(27))
   492  	require.NoError(t, err)
   493  	require.NoError(t, sf.PutBlock(ctx, &blk))
   494  
   495  	//test AccountState() & State()
   496  	testAccount := &state.Account{}
   497  	accountA, err := accountutil.AccountState(ctx, sf, a)
   498  	require.NoError(t, err)
   499  	sHash := hash.BytesToHash160(identityset.Address(28).Bytes())
   500  	_, err = sf.State(testAccount, protocol.LegacyKeyOption(sHash))
   501  	require.NoError(t, err)
   502  	require.Equal(t, accountA, testAccount)
   503  	require.Equal(t, big.NewInt(90), accountA.Balance)
   504  }
   505  
   506  func testHistoryState(sf Factory, t *testing.T, statetx, archive bool) {
   507  	// Create a dummy iotex address
   508  	a := identityset.Address(28)
   509  	b := identityset.Address(31)
   510  	priKeyA := identityset.PrivateKey(28)
   511  	acc := account.NewProtocol(rewarding.DepositGas)
   512  	require.NoError(t, sf.Register(acc))
   513  	ge := genesis.Default
   514  	ge.InitBalanceMap[a.String()] = "100"
   515  	gasLimit := uint64(1000000)
   516  	ctx := protocol.WithBlockCtx(
   517  		context.Background(),
   518  		protocol.BlockCtx{
   519  			BlockHeight: 0,
   520  			Producer:    identityset.Address(27),
   521  			GasLimit:    gasLimit,
   522  		},
   523  	)
   524  	ctx = genesis.WithGenesisContext(ctx, ge)
   525  
   526  	require.NoError(t, sf.Start(ctx))
   527  	defer func() {
   528  		require.NoError(t, sf.Stop(ctx))
   529  	}()
   530  	accountA, err := accountutil.AccountState(ctx, sf, a)
   531  	require.NoError(t, err)
   532  	accountB, err := accountutil.AccountState(ctx, sf, b)
   533  	require.NoError(t, err)
   534  	require.Equal(t, big.NewInt(100), accountA.Balance)
   535  	require.Equal(t, big.NewInt(0), accountB.Balance)
   536  	tsf, err := action.NewTransfer(1, big.NewInt(10), b.String(), nil, uint64(20000), big.NewInt(0))
   537  	require.NoError(t, err)
   538  	bd := &action.EnvelopeBuilder{}
   539  	elp := bd.SetAction(tsf).SetGasLimit(20000).SetNonce(1).Build()
   540  	selp, err := action.Sign(elp, priKeyA)
   541  	require.NoError(t, err)
   542  	ctx = protocol.WithBlockCtx(
   543  		ctx,
   544  		protocol.BlockCtx{
   545  			BlockHeight: 1,
   546  			Producer:    identityset.Address(27),
   547  			GasLimit:    gasLimit,
   548  		},
   549  	)
   550  	ctx = protocol.WithBlockchainCtx(ctx, protocol.BlockchainCtx{
   551  		ChainID: 1,
   552  	})
   553  	blk, err := block.NewTestingBuilder().
   554  		SetHeight(1).
   555  		SetPrevBlockHash(hash.ZeroHash256).
   556  		SetTimeStamp(testutil.TimestampNow()).
   557  		AddActions([]*action.SealedEnvelope{selp}...).
   558  		SignAndBuild(identityset.PrivateKey(27))
   559  	require.NoError(t, err)
   560  	require.NoError(t, sf.PutBlock(ctx, &blk))
   561  
   562  	// check latest balance
   563  	accountA, err = accountutil.AccountState(ctx, sf, a)
   564  	require.NoError(t, err)
   565  	accountB, err = accountutil.AccountState(ctx, sf, b)
   566  	require.NoError(t, err)
   567  	require.Equal(t, big.NewInt(90), accountA.Balance)
   568  	require.Equal(t, big.NewInt(10), accountB.Balance)
   569  
   570  	// check archive data
   571  	if statetx {
   572  		// statetx not support archive mode
   573  		_, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), a)
   574  		require.Equal(t, ErrNotSupported, errors.Cause(err))
   575  		_, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), b)
   576  		require.Equal(t, ErrNotSupported, errors.Cause(err))
   577  	} else {
   578  		if !archive {
   579  			_, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), a)
   580  			require.Equal(t, ErrNoArchiveData, errors.Cause(err))
   581  			_, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), b)
   582  			require.Equal(t, ErrNoArchiveData, errors.Cause(err))
   583  		} else {
   584  			accountA, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), a)
   585  			require.NoError(t, err)
   586  			accountB, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), b)
   587  			require.NoError(t, err)
   588  			require.Equal(t, big.NewInt(100), accountA.Balance)
   589  			require.Equal(t, big.NewInt(0), accountB.Balance)
   590  		}
   591  	}
   592  }
   593  
   594  func testFactoryStates(sf Factory, t *testing.T) {
   595  	// Create a dummy iotex address
   596  	a := identityset.Address(28).String()
   597  	b := identityset.Address(31).String()
   598  	priKeyA := identityset.PrivateKey(28)
   599  	acc := account.NewProtocol(rewarding.DepositGas)
   600  	require.NoError(t, sf.Register(acc))
   601  	ge := genesis.Default
   602  	ge.InitBalanceMap = make(map[string]string)
   603  	ge.InitBalanceMap[a] = "100"
   604  	ge.InitBalanceMap[b] = "100"
   605  	gasLimit := uint64(1000000)
   606  	ctx := protocol.WithBlockCtx(
   607  		context.Background(),
   608  		protocol.BlockCtx{
   609  			BlockHeight: 0,
   610  			Producer:    identityset.Address(27),
   611  			GasLimit:    gasLimit,
   612  		},
   613  	)
   614  	ctx = genesis.WithGenesisContext(ctx, ge)
   615  
   616  	require.NoError(t, sf.Start(ctx))
   617  	defer func() {
   618  		require.NoError(t, sf.Stop(ctx))
   619  	}()
   620  	tsf, err := action.NewTransfer(1, big.NewInt(10), b, nil, uint64(20000), big.NewInt(0))
   621  	require.NoError(t, err)
   622  	bd := &action.EnvelopeBuilder{}
   623  	elp := bd.SetAction(tsf).SetGasLimit(20000).SetNonce(1).Build()
   624  	selp, err := action.Sign(elp, priKeyA)
   625  	require.NoError(t, err)
   626  	ctx = protocol.WithBlockCtx(
   627  		ctx,
   628  		protocol.BlockCtx{
   629  			BlockHeight: 1,
   630  			Producer:    identityset.Address(27),
   631  			GasLimit:    gasLimit,
   632  		},
   633  	)
   634  	ctx = protocol.WithBlockchainCtx(ctx, protocol.BlockchainCtx{
   635  		ChainID: 1,
   636  	})
   637  	blk, err := block.NewTestingBuilder().
   638  		SetHeight(1).
   639  		SetPrevBlockHash(hash.ZeroHash256).
   640  		SetTimeStamp(testutil.TimestampNow()).
   641  		AddActions([]*action.SealedEnvelope{selp}...).
   642  		SignAndBuild(identityset.PrivateKey(27))
   643  	require.NoError(t, err)
   644  	require.NoError(t, sf.PutBlock(ctx, &blk))
   645  
   646  	// case I: check KeyOption
   647  	keyOpt := protocol.KeyOption([]byte(""))
   648  	_, _, err = sf.States(keyOpt)
   649  	require.Equal(t, ErrNotSupported, errors.Cause(err))
   650  
   651  	// case II: check without namespace & keys
   652  	height, iter, err := sf.States()
   653  	require.NoError(t, err)
   654  	require.Equal(t, uint64(1), height)
   655  	// two accounts and one CurrentHeightKey
   656  	require.Equal(t, 3, iter.Size())
   657  	accounts := make([]*state.Account, 0)
   658  	for i := 0; i < iter.Size(); i++ {
   659  		c := &state.Account{}
   660  		err = iter.Next(c)
   661  		if err != nil {
   662  			continue
   663  		}
   664  		accounts = append(accounts, c)
   665  	}
   666  	require.Equal(t, uint64(90), accounts[0].Balance.Uint64())
   667  	require.Equal(t, uint64(110), accounts[1].Balance.Uint64())
   668  
   669  	// case III: check without cond,with AccountKVNamespace namespace,key not exists
   670  	namespaceOpt := protocol.NamespaceOption(AccountKVNamespace)
   671  	height, iter, err = sf.States(namespaceOpt)
   672  	require.NoError(t, err)
   673  	require.Equal(t, uint64(1), height)
   674  	// two accounts and one CurrentHeightKey
   675  	require.Equal(t, 3, iter.Size())
   676  	accounts = make([]*state.Account, 0)
   677  	for i := 0; i < iter.Size(); i++ {
   678  		c := &state.Account{}
   679  		err = iter.Next(c)
   680  		if err != nil {
   681  			continue
   682  		}
   683  		accounts = append(accounts, c)
   684  	}
   685  	require.Equal(t, uint64(90), accounts[0].Balance.Uint64())
   686  	require.Equal(t, uint64(110), accounts[1].Balance.Uint64())
   687  
   688  	// case IV: check without cond,with AccountKVNamespace namespace
   689  	namespaceOpt = protocol.NamespaceOption(AccountKVNamespace)
   690  	height, iter, err = sf.States(namespaceOpt)
   691  	require.NoError(t, err)
   692  	require.Equal(t, uint64(1), height)
   693  	// two accounts and one CurrentHeightKey
   694  	require.Equal(t, 3, iter.Size())
   695  	accounts = make([]*state.Account, 0)
   696  	for i := 0; i < iter.Size(); i++ {
   697  		c := &state.Account{}
   698  		err = iter.Next(c)
   699  		if err != nil {
   700  			continue
   701  		}
   702  		accounts = append(accounts, c)
   703  	}
   704  	require.Equal(t, uint64(90), accounts[0].Balance.Uint64())
   705  	require.Equal(t, uint64(110), accounts[1].Balance.Uint64())
   706  
   707  	// case V: check cond,with AccountKVNamespace namespace
   708  	namespaceOpt = protocol.NamespaceOption(AccountKVNamespace)
   709  	addrHash := hash.BytesToHash160(identityset.Address(28).Bytes())
   710  	height, iter, err = sf.States(namespaceOpt, protocol.KeysOption(func() ([][]byte, error) {
   711  		return [][]byte{addrHash[:]}, nil
   712  	}))
   713  	require.NoError(t, err)
   714  	require.Equal(t, uint64(1), height)
   715  	require.Equal(t, 1, iter.Size())
   716  	accounts = make([]*state.Account, 0)
   717  	for i := 0; i < iter.Size(); i++ {
   718  		c := &state.Account{}
   719  		require.NoError(t, iter.Next(c))
   720  		accounts = append(accounts, c)
   721  	}
   722  	require.Equal(t, uint64(90), accounts[0].Balance.Uint64())
   723  }
   724  
   725  func TestNonce(t *testing.T) {
   726  	testTriePath, err := testutil.PathOfTempFile(_triePath)
   727  	require.NoError(t, err)
   728  	defer testutil.CleanupPath(testTriePath)
   729  
   730  	cfg := DefaultConfig
   731  	db1, err := db.CreateKVStore(db.DefaultConfig, testTriePath)
   732  	require.NoError(t, err)
   733  
   734  	reg := protocol.NewRegistry()
   735  	acc := account.NewProtocol(rewarding.DepositGas)
   736  	err = acc.Register(reg)
   737  	require.NoError(t, err)
   738  
   739  	sf, err := NewFactory(cfg, db1, SkipBlockValidationOption(), RegistryOption(reg))
   740  	require.NoError(t, err)
   741  	testNonce(protocol.WithRegistry(context.Background(), reg), sf, t)
   742  }
   743  
   744  func TestSDBNonce(t *testing.T) {
   745  	testDBPath, err := testutil.PathOfTempFile(_stateDBPath)
   746  	require.NoError(t, err)
   747  	defer testutil.CleanupPath(testDBPath)
   748  
   749  	cfg := DefaultConfig
   750  	cfg.Chain.TrieDBPath = testDBPath
   751  
   752  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   753  	require.NoError(t, err)
   754  
   755  	reg := protocol.NewRegistry()
   756  	acc := account.NewProtocol(rewarding.DepositGas)
   757  	err = acc.Register(reg)
   758  	require.NoError(t, err)
   759  
   760  	sdb, err := NewStateDB(cfg, db2, SkipBlockValidationStateDBOption(), RegistryStateDBOption(reg))
   761  	require.NoError(t, err)
   762  
   763  	testNonce(protocol.WithRegistry(context.Background(), reg), sdb, t)
   764  }
   765  
   766  func testNonce(ctx context.Context, sf Factory, t *testing.T) {
   767  	// Create two dummy iotex address
   768  	a := identityset.Address(28)
   769  	priKeyA := identityset.PrivateKey(28)
   770  	b := identityset.Address(29).String()
   771  	ge := genesis.Default
   772  	ge.InitBalanceMap[a.String()] = "100"
   773  	gasLimit := uint64(1000000)
   774  	ctx = protocol.WithBlockCtx(ctx,
   775  		protocol.BlockCtx{
   776  			BlockHeight: 0,
   777  			Producer:    identityset.Address(27),
   778  			GasLimit:    gasLimit,
   779  		})
   780  	ctx = protocol.WithFeatureCtx(genesis.WithGenesisContext(ctx, ge))
   781  
   782  	require.NoError(t, sf.Start(ctx))
   783  	defer func() {
   784  		require.NoError(t, sf.Stop(ctx))
   785  	}()
   786  	ws, err := sf.(workingSetCreator).newWorkingSet(ctx, 1)
   787  	require.NoError(t, err)
   788  
   789  	tx, err := action.NewTransfer(0, big.NewInt(2), b, nil, uint64(20000), big.NewInt(0))
   790  	require.NoError(t, err)
   791  	bd := &action.EnvelopeBuilder{}
   792  	elp := bd.SetAction(tx).SetNonce(0).SetGasLimit(20000).Build()
   793  	selp, err := action.Sign(elp, priKeyA)
   794  	require.NoError(t, err)
   795  
   796  	ctx = protocol.WithBlockCtx(ctx,
   797  		protocol.BlockCtx{
   798  			BlockHeight: 1,
   799  			Producer:    identityset.Address(27),
   800  			GasLimit:    gasLimit,
   801  		})
   802  	intrinsicGas, err := selp.IntrinsicGas()
   803  	require.NoError(t, err)
   804  	selpHash, err := selp.Hash()
   805  	require.NoError(t, err)
   806  	ctx = protocol.WithActionCtx(
   807  		ctx,
   808  		protocol.ActionCtx{
   809  			Caller:       a,
   810  			ActionHash:   selpHash,
   811  			GasPrice:     selp.GasPrice(),
   812  			Nonce:        selp.Nonce(),
   813  			IntrinsicGas: intrinsicGas,
   814  		},
   815  	)
   816  	ctx = protocol.WithBlockchainCtx(ctx, protocol.BlockchainCtx{
   817  		ChainID: 1,
   818  	})
   819  	_, err = ws.runAction(ctx, selp)
   820  	require.NoError(t, err)
   821  	state, err := accountutil.AccountState(ctx, sf, a)
   822  	require.NoError(t, err)
   823  	require.Equal(t, uint64(1), state.PendingNonce())
   824  
   825  	tx, err = action.NewTransfer(1, big.NewInt(2), b, nil, uint64(20000), big.NewInt(0))
   826  	require.NoError(t, err)
   827  	bd = &action.EnvelopeBuilder{}
   828  	elp = bd.SetAction(tx).SetNonce(1).SetGasLimit(20000).Build()
   829  	selp, err = action.Sign(elp, priKeyA)
   830  	require.NoError(t, err)
   831  
   832  	blk, err := block.NewTestingBuilder().
   833  		SetHeight(1).
   834  		SetPrevBlockHash(hash.ZeroHash256).
   835  		SetTimeStamp(testutil.TimestampNow()).
   836  		AddActions([]*action.SealedEnvelope{selp}...).
   837  		SignAndBuild(identityset.PrivateKey(27))
   838  	require.NoError(t, err)
   839  
   840  	require.NoError(t, sf.PutBlock(ctx, &blk))
   841  	state, err = accountutil.AccountState(ctx, sf, a)
   842  	require.NoError(t, err)
   843  	require.Equal(t, uint64(2), state.PendingNonce())
   844  }
   845  
   846  func TestLoadStoreHeight(t *testing.T) {
   847  	testTriePath, err := testutil.PathOfTempFile(_triePath)
   848  	require.NoError(t, err)
   849  	defer testutil.CleanupPath(testTriePath)
   850  
   851  	cfg := DefaultConfig
   852  	cfg.Chain.TrieDBPath = testTriePath
   853  
   854  	db1, err := db.CreateKVStore(db.DefaultConfig, cfg.Chain.TrieDBPath)
   855  	require.NoError(t, err)
   856  	statefactory, err := NewFactory(cfg, db1, SkipBlockValidationOption())
   857  	require.NoError(t, err)
   858  
   859  	testLoadStoreHeight(statefactory, t)
   860  }
   861  
   862  func TestLoadStoreHeightInMem(t *testing.T) {
   863  	testTriePath, err := testutil.PathOfTempFile(_triePath)
   864  	require.NoError(t, err)
   865  	defer testutil.CleanupPath(testTriePath)
   866  
   867  	cfg := DefaultConfig
   868  	cfg.Chain.TrieDBPath = testTriePath
   869  	statefactory, err := NewFactory(cfg, db.NewMemKVStore(), SkipBlockValidationOption())
   870  	require.NoError(t, err)
   871  	testLoadStoreHeight(statefactory, t)
   872  }
   873  
   874  func TestSDBLoadStoreHeight(t *testing.T) {
   875  	testDBPath, err := testutil.PathOfTempFile(_stateDBPath)
   876  	require.NoError(t, err)
   877  	defer testutil.CleanupPath(testDBPath)
   878  
   879  	cfg := DefaultConfig
   880  	cfg.Chain.TrieDBPath = testDBPath
   881  
   882  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   883  	require.NoError(t, err)
   884  	db, err := NewStateDB(cfg, db2, SkipBlockValidationStateDBOption())
   885  	require.NoError(t, err)
   886  
   887  	testLoadStoreHeight(db, t)
   888  }
   889  
   890  func TestSDBLoadStoreHeightInMem(t *testing.T) {
   891  	testDBPath, err := testutil.PathOfTempFile(_stateDBPath)
   892  	require.NoError(t, err)
   893  	defer testutil.CleanupPath(testDBPath)
   894  	cfg := DefaultConfig
   895  	cfg.Chain.TrieDBPath = testDBPath
   896  	db, err := NewStateDB(cfg, db.NewMemKVStore(), SkipBlockValidationStateDBOption())
   897  	require.NoError(t, err)
   898  
   899  	testLoadStoreHeight(db, t)
   900  }
   901  
   902  func testLoadStoreHeight(sf Factory, t *testing.T) {
   903  	require := require.New(t)
   904  	ctx := genesis.WithGenesisContext(context.Background(), genesis.Default)
   905  	require.NoError(sf.Start(ctx))
   906  	defer func() {
   907  		require.NoError(sf.Stop(ctx))
   908  	}()
   909  	height, err := sf.Height()
   910  	require.NoError(err)
   911  	require.Equal(uint64(0), height)
   912  	lastBlockHash := hash.ZeroHash256
   913  	for i := uint64(1); i <= 10; i++ {
   914  		ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{
   915  			BlockHeight: i,
   916  			Producer:    identityset.Address(27),
   917  			GasLimit:    testutil.TestGasLimit,
   918  		})
   919  		blk, err := block.NewTestingBuilder().
   920  			SetHeight(i).
   921  			SetPrevBlockHash(lastBlockHash).
   922  			SetTimeStamp(testutil.TimestampNow()).
   923  			AddActions([]*action.SealedEnvelope{}...).
   924  			SignAndBuild(identityset.PrivateKey(27))
   925  		require.NoError(err)
   926  		require.NoError(sf.PutBlock(ctx, &blk))
   927  
   928  		height, err = sf.Height()
   929  		require.NoError(err)
   930  		require.Equal(uint64(i), height)
   931  	}
   932  }
   933  
   934  func TestRunActions(t *testing.T) {
   935  	require := require.New(t)
   936  	testTriePath, err := testutil.PathOfTempFile(_triePath)
   937  	require.NoError(err)
   938  
   939  	cfg := DefaultConfig
   940  	db1, err := db.CreateKVStore(db.DefaultConfig, testTriePath)
   941  	require.NoError(err)
   942  	cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100"
   943  	cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "200"
   944  	registry := protocol.NewRegistry()
   945  	sf, err := NewFactory(cfg, db1, RegistryOption(registry), SkipBlockValidationOption())
   946  	require.NoError(err)
   947  
   948  	acc := account.NewProtocol(rewarding.DepositGas)
   949  	require.NoError(acc.Register(registry))
   950  	ctx := protocol.WithBlockCtx(
   951  		genesis.WithGenesisContext(context.Background(), cfg.Genesis),
   952  		protocol.BlockCtx{},
   953  	)
   954  	require.NoError(sf.Start(ctx))
   955  	defer func() {
   956  		require.NoError(sf.Stop(ctx))
   957  		testutil.CleanupPath(testTriePath)
   958  	}()
   959  	testCommit(sf, t)
   960  }
   961  
   962  func TestSTXRunActions(t *testing.T) {
   963  	require := require.New(t)
   964  	testStateDBPath, err := testutil.PathOfTempFile(_stateDBPath)
   965  	require.NoError(err)
   966  
   967  	cfg := DefaultConfig
   968  	cfg.Chain.TrieDBPath = testStateDBPath
   969  	cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100"
   970  	cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "200"
   971  
   972  	registry := protocol.NewRegistry()
   973  	acc := account.NewProtocol(rewarding.DepositGas)
   974  	require.NoError(acc.Register(registry))
   975  
   976  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   977  	require.NoError(err)
   978  	sdb, err := NewStateDB(cfg, db2, SkipBlockValidationStateDBOption(), RegistryStateDBOption(registry))
   979  	require.NoError(err)
   980  
   981  	ctx := protocol.WithBlockCtx(
   982  		genesis.WithGenesisContext(context.Background(), cfg.Genesis),
   983  		protocol.BlockCtx{},
   984  	)
   985  	require.NoError(sdb.Start(ctx))
   986  	defer func() {
   987  		require.NoError(sdb.Stop(ctx))
   988  		testutil.CleanupPath(testStateDBPath)
   989  	}()
   990  	testCommit(sdb, t)
   991  }
   992  
   993  func testCommit(factory Factory, t *testing.T) {
   994  	require := require.New(t)
   995  	a := identityset.Address(28).String()
   996  	priKeyA := identityset.PrivateKey(28)
   997  	b := identityset.Address(29).String()
   998  	priKeyB := identityset.PrivateKey(29)
   999  
  1000  	tx1, err := action.NewTransfer(uint64(1), big.NewInt(10), b, nil, uint64(100000), big.NewInt(0))
  1001  	require.NoError(err)
  1002  	bd := &action.EnvelopeBuilder{}
  1003  	elp := bd.SetNonce(1).SetAction(tx1).Build()
  1004  	selp1, err := action.Sign(elp, priKeyA)
  1005  	require.NoError(err)
  1006  
  1007  	tx2, err := action.NewTransfer(uint64(1), big.NewInt(20), a, nil, uint64(100000), big.NewInt(0))
  1008  	require.NoError(err)
  1009  	bd = &action.EnvelopeBuilder{}
  1010  	elp = bd.SetNonce(1).SetAction(tx2).Build()
  1011  	selp2, err := action.Sign(elp, priKeyB)
  1012  	require.NoError(err)
  1013  
  1014  	blkHash, err := selp1.Hash()
  1015  	require.NoError(err)
  1016  
  1017  	gasLimit := uint64(1000000)
  1018  	ctx := protocol.WithBlockCtx(context.Background(),
  1019  		protocol.BlockCtx{
  1020  			BlockHeight: 1,
  1021  			Producer:    identityset.Address(27),
  1022  			GasLimit:    gasLimit,
  1023  		})
  1024  	ctx = genesis.WithGenesisContext(
  1025  		protocol.WithBlockchainCtx(
  1026  			ctx,
  1027  			protocol.BlockchainCtx{
  1028  				Tip: protocol.TipInfo{
  1029  					Height: 0,
  1030  					Hash:   blkHash,
  1031  				},
  1032  			}),
  1033  		genesis.Default,
  1034  	)
  1035  
  1036  	blk, err := block.NewTestingBuilder().
  1037  		SetHeight(1).
  1038  		SetPrevBlockHash(blkHash).
  1039  		SetTimeStamp(testutil.TimestampNow()).
  1040  		AddActions(selp1, selp2).
  1041  		SignAndBuild(identityset.PrivateKey(27))
  1042  	require.NoError(err)
  1043  
  1044  	require.NoError(factory.PutBlock(ctx, &blk))
  1045  }
  1046  
  1047  func TestPickAndRunActions(t *testing.T) {
  1048  	require := require.New(t)
  1049  	testTriePath, err := testutil.PathOfTempFile(_triePath)
  1050  	require.NoError(err)
  1051  
  1052  	cfg := DefaultConfig
  1053  	db1, err := db.CreateKVStore(db.DefaultConfig, testTriePath)
  1054  	require.NoError(err)
  1055  	cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100"
  1056  	cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "200"
  1057  	registry := protocol.NewRegistry()
  1058  	sf, err := NewFactory(cfg, db1, RegistryOption(registry))
  1059  	require.NoError(err)
  1060  
  1061  	acc := account.NewProtocol(rewarding.DepositGas)
  1062  	require.NoError(acc.Register(registry))
  1063  	ctx := protocol.WithBlockCtx(
  1064  		genesis.WithGenesisContext(context.Background(), cfg.Genesis),
  1065  		protocol.BlockCtx{},
  1066  	)
  1067  	require.NoError(sf.Start(ctx))
  1068  	defer func() {
  1069  		require.NoError(sf.Stop(ctx))
  1070  		testutil.CleanupPath(testTriePath)
  1071  	}()
  1072  	testNewBlockBuilder(sf, t)
  1073  }
  1074  
  1075  func TestSTXPickAndRunActions(t *testing.T) {
  1076  	require := require.New(t)
  1077  	testStateDBPath, err := testutil.PathOfTempFile(_stateDBPath)
  1078  	require.NoError(err)
  1079  
  1080  	cfg := DefaultConfig
  1081  	cfg.Chain.TrieDBPath = testStateDBPath
  1082  	cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100"
  1083  	cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "200"
  1084  	registry := protocol.NewRegistry()
  1085  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
  1086  	require.NoError(err)
  1087  	sdb, err := NewStateDB(cfg, db2, RegistryStateDBOption(registry))
  1088  	require.NoError(err)
  1089  
  1090  	acc := account.NewProtocol(rewarding.DepositGas)
  1091  	require.NoError(acc.Register(registry))
  1092  	ctx := protocol.WithBlockCtx(
  1093  		genesis.WithGenesisContext(context.Background(), cfg.Genesis),
  1094  		protocol.BlockCtx{},
  1095  	)
  1096  	require.NoError(sdb.Start(ctx))
  1097  	defer func() {
  1098  		require.NoError(sdb.Stop(ctx))
  1099  		testutil.CleanupPath(testStateDBPath)
  1100  	}()
  1101  	testNewBlockBuilder(sdb, t)
  1102  }
  1103  
  1104  func testNewBlockBuilder(factory Factory, t *testing.T) {
  1105  	require := require.New(t)
  1106  	a := identityset.Address(28).String()
  1107  	priKeyA := identityset.PrivateKey(28)
  1108  	b := identityset.Address(29).String()
  1109  	priKeyB := identityset.PrivateKey(29)
  1110  
  1111  	accMap := make(map[string][]*action.SealedEnvelope)
  1112  	tx1, err := action.NewTransfer(uint64(1), big.NewInt(10), b, nil, uint64(100000), big.NewInt(0))
  1113  	require.NoError(err)
  1114  	bd := &action.EnvelopeBuilder{}
  1115  	elp := bd.SetNonce(1).SetAction(tx1).Build()
  1116  	selp1, err := action.Sign(elp, priKeyA)
  1117  	require.NoError(err)
  1118  	accMap[identityset.Address(28).String()] = []*action.SealedEnvelope{selp1}
  1119  
  1120  	addr0 := identityset.Address(27).String()
  1121  	tsf0, err := action.SignedTransfer(addr0, identityset.PrivateKey(0), 1, big.NewInt(90000000), nil, testutil.TestGasLimit, big.NewInt(testutil.TestGasPriceInt64))
  1122  	require.NoError(err)
  1123  	accMap[identityset.Address(0).String()] = []*action.SealedEnvelope{tsf0}
  1124  
  1125  	tx2, err := action.NewTransfer(uint64(1), big.NewInt(20), a, nil, uint64(100000), big.NewInt(0))
  1126  	require.NoError(err)
  1127  	bd = &action.EnvelopeBuilder{}
  1128  	elp = bd.SetNonce(1).SetAction(tx2).Build()
  1129  	selp2, err := action.Sign(elp, priKeyB)
  1130  	require.NoError(err)
  1131  	accMap[identityset.Address(29).String()] = []*action.SealedEnvelope{selp2}
  1132  	ctrl := gomock.NewController(t)
  1133  	ap := mock_actpool.NewMockActPool(ctrl)
  1134  	ap.EXPECT().PendingActionMap().Return(accMap).Times(1)
  1135  	gasLimit := uint64(1000000)
  1136  	ctx := protocol.WithBlockCtx(context.Background(),
  1137  		protocol.BlockCtx{
  1138  			BlockHeight: 1,
  1139  			Producer:    identityset.Address(27),
  1140  			GasLimit:    gasLimit,
  1141  		})
  1142  	ctx = protocol.WithBlockchainCtx(
  1143  		genesis.WithGenesisContext(ctx, genesis.Default),
  1144  		protocol.BlockchainCtx{},
  1145  	)
  1146  	ctx = protocol.WithFeatureCtx(protocol.WithFeatureWithHeightCtx(ctx))
  1147  	blkBuilder, err := factory.NewBlockBuilder(ctx, ap, nil)
  1148  	require.NoError(err)
  1149  	require.NotNil(blkBuilder)
  1150  	blk, err := blkBuilder.SignAndBuild(identityset.PrivateKey(27))
  1151  	require.NoError(err)
  1152  	require.NoError(factory.PutBlock(ctx, &blk))
  1153  }
  1154  
  1155  func TestSimulateExecution(t *testing.T) {
  1156  	require := require.New(t)
  1157  	testTriePath, err := testutil.PathOfTempFile(_triePath)
  1158  	require.NoError(err)
  1159  
  1160  	cfg := DefaultConfig
  1161  	db1, err := db.CreateKVStore(db.DefaultConfig, testTriePath)
  1162  	require.NoError(err)
  1163  	cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100"
  1164  	cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "200"
  1165  	registry := protocol.NewRegistry()
  1166  	sf, err := NewFactory(cfg, db1, RegistryOption(registry))
  1167  	require.NoError(err)
  1168  
  1169  	acc := account.NewProtocol(rewarding.DepositGas)
  1170  	require.NoError(acc.Register(registry))
  1171  	ctx := protocol.WithBlockchainCtx(
  1172  		protocol.WithBlockCtx(
  1173  			genesis.WithGenesisContext(context.Background(), cfg.Genesis),
  1174  			protocol.BlockCtx{},
  1175  		),
  1176  		protocol.BlockchainCtx{},
  1177  	)
  1178  	require.NoError(sf.Start(ctx))
  1179  	defer func() {
  1180  		require.NoError(sf.Stop(ctx))
  1181  		testutil.CleanupPath(testTriePath)
  1182  	}()
  1183  	testSimulateExecution(ctx, sf, t)
  1184  }
  1185  
  1186  func TestSTXSimulateExecution(t *testing.T) {
  1187  	require := require.New(t)
  1188  	testStateDBPath, err := testutil.PathOfTempFile(_stateDBPath)
  1189  	require.NoError(err)
  1190  
  1191  	cfg := DefaultConfig
  1192  	cfg.Chain.TrieDBPath = testStateDBPath
  1193  	cfg.Genesis.InitBalanceMap[identityset.Address(28).String()] = "100"
  1194  	cfg.Genesis.InitBalanceMap[identityset.Address(29).String()] = "200"
  1195  	registry := protocol.NewRegistry()
  1196  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
  1197  	require.NoError(err)
  1198  	sdb, err := NewStateDB(cfg, db2, RegistryStateDBOption(registry))
  1199  	require.NoError(err)
  1200  
  1201  	acc := account.NewProtocol(rewarding.DepositGas)
  1202  	require.NoError(acc.Register(registry))
  1203  	ctx := protocol.WithBlockchainCtx(
  1204  		protocol.WithBlockCtx(
  1205  			genesis.WithGenesisContext(context.Background(), cfg.Genesis),
  1206  			protocol.BlockCtx{},
  1207  		),
  1208  		protocol.BlockchainCtx{},
  1209  	)
  1210  	require.NoError(sdb.Start(ctx))
  1211  	defer func() {
  1212  		require.NoError(sdb.Stop(ctx))
  1213  		testutil.CleanupPath(testStateDBPath)
  1214  	}()
  1215  	testSimulateExecution(ctx, sdb, t)
  1216  }
  1217  
  1218  func testSimulateExecution(ctx context.Context, sf Factory, t *testing.T) {
  1219  	require := require.New(t)
  1220  
  1221  	data, _ := hex.DecodeString("608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582002faabbefbbda99b20217cf33cb8ab8100caf1542bf1f48117d72e2c59139aea0029")
  1222  	ex, err := action.NewExecution(action.EmptyAddress, 1, big.NewInt(0), uint64(100000), big.NewInt(0), data)
  1223  	require.NoError(err)
  1224  	addr, err := address.FromString(address.ZeroAddress)
  1225  	require.NoError(err)
  1226  
  1227  	ctx = evm.WithHelperCtx(ctx, evm.HelperContext{
  1228  		GetBlockHash: func(uint64) (hash.Hash256, error) {
  1229  			return hash.ZeroHash256, nil
  1230  		},
  1231  		GetBlockTime: func(u uint64) (time.Time, error) {
  1232  			return time.Time{}, nil
  1233  		},
  1234  	})
  1235  	_, _, err = sf.SimulateExecution(ctx, addr, ex)
  1236  	require.NoError(err)
  1237  }
  1238  
  1239  func TestCachedBatch(t *testing.T) {
  1240  	sf, err := NewFactory(DefaultConfig, db.NewMemKVStore())
  1241  	require.NoError(t, err)
  1242  	ctx := genesis.WithGenesisContext(
  1243  		protocol.WithRegistry(context.Background(), protocol.NewRegistry()),
  1244  		genesis.Default,
  1245  	)
  1246  	require.NoError(t, sf.Start(ctx))
  1247  	ws, err := sf.(workingSetCreator).newWorkingSet(ctx, 1)
  1248  	require.NoError(t, err)
  1249  	testCachedBatch(ws, t)
  1250  }
  1251  
  1252  func TestSTXCachedBatch(t *testing.T) {
  1253  	sdb, err := NewStateDB(DefaultConfig, db.NewMemKVStore())
  1254  	require.NoError(t, err)
  1255  	ctx := genesis.WithGenesisContext(
  1256  		protocol.WithRegistry(context.Background(), protocol.NewRegistry()),
  1257  		genesis.Default,
  1258  	)
  1259  	require.NoError(t, sdb.Start(ctx))
  1260  	ws, err := sdb.(workingSetCreator).newWorkingSet(ctx, 1)
  1261  	require.NoError(t, err)
  1262  	testCachedBatch(ws, t)
  1263  }
  1264  
  1265  func testCachedBatch(ws *workingSet, t *testing.T) {
  1266  	require := require.New(t)
  1267  
  1268  	// test PutState()
  1269  	hashA := hash.BytesToHash160(identityset.Address(28).Bytes())
  1270  	accountA, err := state.NewAccount()
  1271  	require.NoError(err)
  1272  	require.NoError(accountA.AddBalance(big.NewInt(70)))
  1273  	_, err = ws.PutState(accountA, protocol.LegacyKeyOption(hashA))
  1274  	require.NoError(err)
  1275  
  1276  	// test State()
  1277  	testAccount := &state.Account{}
  1278  	_, err = ws.State(testAccount, protocol.LegacyKeyOption(hashA))
  1279  	require.NoError(err)
  1280  	require.Equal(accountA, testAccount)
  1281  
  1282  	// test DelState()
  1283  	_, err = ws.DelState(protocol.LegacyKeyOption(hashA))
  1284  	require.NoError(err)
  1285  
  1286  	// can't state account "alfa" anymore
  1287  	_, err = ws.State(testAccount, protocol.LegacyKeyOption(hashA))
  1288  	require.Error(err)
  1289  }
  1290  
  1291  func TestStateDBPatch(t *testing.T) {
  1292  	require := require.New(t)
  1293  	n1 := "n1"
  1294  	n2 := "n2"
  1295  	a1 := "a1"
  1296  	a2 := "a2"
  1297  	b11 := "bb11"
  1298  	b12 := "bb12"
  1299  	b21 := "bb21"
  1300  	b22 := "bb22"
  1301  	ha1, err := hex.DecodeString(a1)
  1302  	require.NoError(err)
  1303  	ha2, err := hex.DecodeString(a2)
  1304  	require.NoError(err)
  1305  	hb11, err := hex.DecodeString(b11)
  1306  	require.NoError(err)
  1307  	hb12, err := hex.DecodeString(b12)
  1308  	require.NoError(err)
  1309  	hb21, err := hex.DecodeString(b21)
  1310  	require.NoError(err)
  1311  	hb22, err := hex.DecodeString(b22)
  1312  	require.NoError(err)
  1313  	patchTest := [][]string{
  1314  		{"1", "PUT", n1, a1, b11},
  1315  		{"1", "PUT", n1, a2, b12},
  1316  		{"1", "PUT", n2, a1, b21},
  1317  		{"2", "DELETE", n1, a1},
  1318  		{"2", "PUT", n2, a2, b22},
  1319  	}
  1320  	patchFile, err := testutil.PathOfTempFile(_triePath + ".patch")
  1321  	require.NoError(err)
  1322  	f, err := os.Create(patchFile)
  1323  	require.NoError(err)
  1324  	require.NoError(csv.NewWriter(f).WriteAll(patchTest))
  1325  	require.NoError(f.Close())
  1326  
  1327  	testDBPath, err := testutil.PathOfTempFile(_stateDBPath)
  1328  	require.NoError(err)
  1329  	cfg := DefaultConfig
  1330  	dbcfg := db.DefaultConfig
  1331  	dbcfg.DbPath = testDBPath
  1332  	cfg.Chain.TrieDBPatchFile = patchFile
  1333  	trieDB := db.NewBoltDB(dbcfg)
  1334  	sdb, err := NewStateDB(cfg, trieDB, DefaultPatchOption(), SkipBlockValidationStateDBOption())
  1335  	require.NoError(err)
  1336  	gasLimit := testutil.TestGasLimit
  1337  
  1338  	ctx := protocol.WithBlockCtx(
  1339  		context.Background(),
  1340  		protocol.BlockCtx{
  1341  			BlockHeight: 0,
  1342  			Producer:    identityset.Address(27),
  1343  			GasLimit:    gasLimit,
  1344  		},
  1345  	)
  1346  	ctx = genesis.WithGenesisContext(ctx, genesis.Default)
  1347  
  1348  	require.NoError(sdb.Start(ctx))
  1349  	defer func() {
  1350  		require.NoError(sdb.Stop(ctx))
  1351  		testutil.CleanupPath(patchFile)
  1352  		testutil.CleanupPath(testDBPath)
  1353  	}()
  1354  	ctx = protocol.WithBlockchainCtx(protocol.WithBlockCtx(ctx,
  1355  		protocol.BlockCtx{
  1356  			BlockHeight: 1,
  1357  			Producer:    identityset.Address(27),
  1358  			GasLimit:    gasLimit,
  1359  		}), protocol.BlockchainCtx{
  1360  		ChainID: 1,
  1361  	})
  1362  	_, err = trieDB.Get(n1, ha1)
  1363  	require.EqualError(errors.Cause(err), db.ErrNotExist.Error())
  1364  	_, err = trieDB.Get(n1, ha2)
  1365  	require.EqualError(errors.Cause(err), db.ErrNotExist.Error())
  1366  	_, err = trieDB.Get(n2, ha1)
  1367  	require.EqualError(errors.Cause(err), db.ErrNotExist.Error())
  1368  	_, err = trieDB.Get(n2, ha2)
  1369  	require.EqualError(errors.Cause(err), db.ErrNotExist.Error())
  1370  	blk1, err := block.NewTestingBuilder().
  1371  		SetHeight(1).
  1372  		SetPrevBlockHash(hash.ZeroHash256).
  1373  		SetTimeStamp(testutil.TimestampNow()).
  1374  		SignAndBuild(identityset.PrivateKey(27))
  1375  	require.NoError(err)
  1376  	require.NoError(sdb.PutBlock(ctx, &blk1))
  1377  	v11, err := trieDB.Get(n1, ha1)
  1378  	require.NoError(err)
  1379  	require.Equal(v11, hb11)
  1380  	v12, err := trieDB.Get(n1, ha2)
  1381  	require.NoError(err)
  1382  	require.Equal(v12, hb12)
  1383  	v21, err := trieDB.Get(n2, ha1)
  1384  	require.NoError(err)
  1385  	require.Equal(v21, hb21)
  1386  	_, err = trieDB.Get(n2, ha2)
  1387  	require.EqualError(errors.Cause(err), db.ErrNotExist.Error())
  1388  	ctx = protocol.WithBlockchainCtx(protocol.WithBlockCtx(ctx,
  1389  		protocol.BlockCtx{
  1390  			BlockHeight: 2,
  1391  			Producer:    identityset.Address(27),
  1392  			GasLimit:    gasLimit,
  1393  		}), protocol.BlockchainCtx{
  1394  		ChainID: 1,
  1395  	})
  1396  	blk2, err := block.NewTestingBuilder().
  1397  		SetHeight(2).
  1398  		SetPrevBlockHash(blk1.HashBlock()).
  1399  		SetTimeStamp(testutil.TimestampNow()).
  1400  		SignAndBuild(identityset.PrivateKey(27))
  1401  	require.NoError(err)
  1402  	require.NoError(sdb.PutBlock(ctx, &blk2))
  1403  	_, err = trieDB.Get(n1, ha1)
  1404  	require.EqualError(errors.Cause(err), db.ErrNotExist.Error())
  1405  	v12, err = trieDB.Get(n1, ha2)
  1406  	require.NoError(err)
  1407  	require.Equal(v12, hb12)
  1408  	v21, err = trieDB.Get(n2, ha1)
  1409  	require.NoError(err)
  1410  	require.Equal(v21, hb21)
  1411  	v22, err := trieDB.Get(n2, ha2)
  1412  	require.NoError(err)
  1413  	require.Equal(v22, hb22)
  1414  
  1415  	require.NoError(os.RemoveAll(patchFile))
  1416  }
  1417  
  1418  func TestDeleteAndPutSameKey(t *testing.T) {
  1419  	testDeleteAndPutSameKey := func(t *testing.T, ws *workingSet) {
  1420  		key := hash.Hash160b([]byte("test"))
  1421  		acc, err := state.NewAccount()
  1422  		require.NoError(t, err)
  1423  		require.NoError(t, acc.SetPendingNonce(1))
  1424  		require.NoError(t, acc.SetPendingNonce(2))
  1425  		_, err = ws.PutState(acc, protocol.LegacyKeyOption(key))
  1426  		require.NoError(t, err)
  1427  		_, err = ws.DelState(protocol.LegacyKeyOption(key))
  1428  		require.NoError(t, err)
  1429  		_, err = ws.State(acc, protocol.LegacyKeyOption(key))
  1430  		require.Equal(t, state.ErrStateNotExist, errors.Cause(err))
  1431  		_, err = ws.State(acc, protocol.LegacyKeyOption(hash.Hash160b([]byte("other"))))
  1432  		require.Equal(t, state.ErrStateNotExist, errors.Cause(err))
  1433  	}
  1434  	ctx := genesis.WithGenesisContext(
  1435  		protocol.WithRegistry(context.Background(), protocol.NewRegistry()),
  1436  		genesis.Default,
  1437  	)
  1438  	t.Run("workingSet", func(t *testing.T) {
  1439  		sf, err := NewFactory(DefaultConfig, db.NewMemKVStore())
  1440  		require.NoError(t, err)
  1441  		ws, err := sf.(workingSetCreator).newWorkingSet(ctx, 0)
  1442  		require.NoError(t, err)
  1443  		testDeleteAndPutSameKey(t, ws)
  1444  	})
  1445  	t.Run("stateTx", func(t *testing.T) {
  1446  		sdb, err := NewStateDB(DefaultConfig, db.NewMemKVStore())
  1447  		require.NoError(t, err)
  1448  		ws, err := sdb.(workingSetCreator).newWorkingSet(ctx, 0)
  1449  		require.NoError(t, err)
  1450  		testDeleteAndPutSameKey(t, ws)
  1451  	})
  1452  }
  1453  
  1454  func BenchmarkInMemRunAction(b *testing.B) {
  1455  	cfg := DefaultConfig
  1456  	sf, err := NewFactory(cfg, db.NewMemKVStore(), SkipBlockValidationOption())
  1457  	if err != nil {
  1458  		b.Fatal(err)
  1459  	}
  1460  	benchRunAction(sf, b)
  1461  }
  1462  
  1463  func BenchmarkDBRunAction(b *testing.B) {
  1464  	tp := filepath.Join(os.TempDir(), _triePath)
  1465  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1466  		b.Error("Fail to remove testDB file")
  1467  	}
  1468  
  1469  	cfg := DefaultConfig
  1470  	db1, err := db.CreateKVStore(db.DefaultConfig, tp)
  1471  	require.NoError(b, err)
  1472  	sf, err := NewFactory(cfg, db1, SkipBlockValidationOption())
  1473  	if err != nil {
  1474  		b.Fatal(err)
  1475  	}
  1476  	benchRunAction(sf, b)
  1477  
  1478  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1479  		b.Error("Fail to remove testDB file")
  1480  	}
  1481  }
  1482  
  1483  func BenchmarkSDBInMemRunAction(b *testing.B) {
  1484  	cfg := DefaultConfig
  1485  	sdb, err := NewStateDB(cfg, db.NewMemKVStore(), SkipBlockValidationStateDBOption())
  1486  	if err != nil {
  1487  		b.Fatal(err)
  1488  	}
  1489  	benchRunAction(sdb, b)
  1490  }
  1491  
  1492  func BenchmarkSDBRunAction(b *testing.B) {
  1493  	tp := filepath.Join(os.TempDir(), _stateDBPath)
  1494  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1495  		b.Error("Fail to remove testDB file")
  1496  	}
  1497  	cfg := DefaultConfig
  1498  	cfg.Chain.TrieDBPath = tp
  1499  	db1, err := db.CreateKVStore(db.DefaultConfig, cfg.Chain.TrieDBPath)
  1500  	require.NoError(b, err)
  1501  	sdb, err := NewStateDB(cfg, db1, SkipBlockValidationStateDBOption())
  1502  	if err != nil {
  1503  		b.Fatal(err)
  1504  	}
  1505  	benchRunAction(sdb, b)
  1506  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1507  		b.Error("Fail to remove testDB file")
  1508  	}
  1509  }
  1510  
  1511  func BenchmarkCachedSDBRunAction(b *testing.B) {
  1512  	tp := filepath.Join(os.TempDir(), _stateDBPath)
  1513  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1514  		b.Error("Fail to remove testDB file")
  1515  	}
  1516  	cfg := DefaultConfig
  1517  	cfg.Chain.TrieDBPath = tp
  1518  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
  1519  	require.NoError(b, err)
  1520  	sdb, err := NewStateDB(cfg, db2, SkipBlockValidationStateDBOption())
  1521  	if err != nil {
  1522  		b.Fatal(err)
  1523  	}
  1524  	benchRunAction(sdb, b)
  1525  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1526  		b.Error("Fail to remove testDB file")
  1527  	}
  1528  }
  1529  
  1530  func benchRunAction(sf Factory, b *testing.B) {
  1531  	// set up
  1532  	accounts := []string{
  1533  		identityset.Address(28).String(),
  1534  		identityset.Address(29).String(),
  1535  		identityset.Address(30).String(),
  1536  		identityset.Address(31).String(),
  1537  		identityset.Address(32).String(),
  1538  		identityset.Address(33).String(),
  1539  	}
  1540  	pubKeys := []crypto.PublicKey{
  1541  		identityset.PrivateKey(28).PublicKey(),
  1542  		identityset.PrivateKey(29).PublicKey(),
  1543  		identityset.PrivateKey(30).PublicKey(),
  1544  		identityset.PrivateKey(31).PublicKey(),
  1545  		identityset.PrivateKey(32).PublicKey(),
  1546  		identityset.PrivateKey(33).PublicKey(),
  1547  	}
  1548  	nonces := make([]uint64, len(accounts))
  1549  	ge := genesis.Default
  1550  	prevHash := ge.Hash()
  1551  	for _, acc := range accounts {
  1552  		ge.InitBalanceMap[acc] = big.NewInt(int64(b.N * 100)).String()
  1553  	}
  1554  	acc := account.NewProtocol(rewarding.DepositGas)
  1555  	if err := sf.Register(acc); err != nil {
  1556  		b.Fatal(err)
  1557  	}
  1558  	ctx := genesis.WithGenesisContext(context.Background(), ge)
  1559  
  1560  	if err := sf.Start(ctx); err != nil {
  1561  		b.Fatal(err)
  1562  	}
  1563  	defer func() {
  1564  		if err := sf.Stop(ctx); err != nil {
  1565  			b.Fatal(err)
  1566  		}
  1567  	}()
  1568  
  1569  	gasLimit := testutil.TestGasLimit * 100000
  1570  
  1571  	for n := 1; n < b.N; n++ {
  1572  		// put 500 actions together to run
  1573  		b.StopTimer()
  1574  		total := 500
  1575  		acts := make([]*action.SealedEnvelope, 0, total)
  1576  		for numActs := 0; numActs < total; numActs++ {
  1577  			senderIdx := rand.Int() % len(accounts)
  1578  
  1579  			var chainIDBytes [4]byte
  1580  			enc.MachineEndian.PutUint32(chainIDBytes[:], 1)
  1581  			payload := []byte(randStringRunes(20))
  1582  			receiverAddr, err := address.FromBytes(payload)
  1583  			if err != nil {
  1584  				b.Fatal(err)
  1585  			}
  1586  			receiver := receiverAddr.String()
  1587  			nonces[senderIdx] += nonces[senderIdx]
  1588  			tx, err := action.NewTransfer(nonces[senderIdx], big.NewInt(1), receiver, nil, uint64(0), big.NewInt(0))
  1589  			if err != nil {
  1590  				b.Fatal(err)
  1591  			}
  1592  			bd := &action.EnvelopeBuilder{}
  1593  			elp := bd.SetNonce(nonces[senderIdx]).SetAction(tx).Build()
  1594  			selp := action.FakeSeal(elp, pubKeys[senderIdx])
  1595  			acts = append(acts, selp)
  1596  		}
  1597  		b.StartTimer()
  1598  		zctx := protocol.WithBlockCtx(context.Background(),
  1599  			protocol.BlockCtx{
  1600  				BlockHeight: uint64(n),
  1601  				Producer:    identityset.Address(27),
  1602  				GasLimit:    gasLimit,
  1603  			})
  1604  		zctx = genesis.WithGenesisContext(zctx, genesis.Default)
  1605  
  1606  		blk, err := block.NewTestingBuilder().
  1607  			SetHeight(uint64(n)).
  1608  			SetPrevBlockHash(prevHash).
  1609  			SetTimeStamp(testutil.TimestampNow()).
  1610  			AddActions(acts...).
  1611  			SignAndBuild(identityset.PrivateKey(27))
  1612  		if err != nil {
  1613  			b.Fatal(err)
  1614  		}
  1615  
  1616  		if err := sf.PutBlock(zctx, &blk); err != nil {
  1617  			b.Fatal(err)
  1618  		}
  1619  		prevHash = blk.HashBlock()
  1620  	}
  1621  }
  1622  
  1623  func BenchmarkSDBState(b *testing.B) {
  1624  	tp := filepath.Join(os.TempDir(), _stateDBPath)
  1625  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1626  		b.Error("Fail to remove testDB file")
  1627  	}
  1628  	cfg := DefaultConfig
  1629  	cfg.Chain.TrieDBPath = tp
  1630  	db1, err := db.CreateKVStore(db.DefaultConfig, cfg.Chain.TrieDBPath)
  1631  	require.NoError(b, err)
  1632  	sdb, err := NewStateDB(cfg, db1, SkipBlockValidationStateDBOption())
  1633  	if err != nil {
  1634  		b.Fatal(err)
  1635  	}
  1636  	benchState(sdb, b)
  1637  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1638  		b.Error("Fail to remove testDB file")
  1639  	}
  1640  }
  1641  
  1642  func BenchmarkCachedSDBState(b *testing.B) {
  1643  	tp := filepath.Join(os.TempDir(), _stateDBPath)
  1644  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1645  		b.Error("Fail to remove testDB file")
  1646  	}
  1647  	cfg := DefaultConfig
  1648  	cfg.Chain.TrieDBPath = tp
  1649  	db2, err := db.CreateKVStoreWithCache(db.DefaultConfig, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
  1650  	require.NoError(b, err)
  1651  	sdb, err := NewStateDB(cfg, db2, SkipBlockValidationStateDBOption())
  1652  	if err != nil {
  1653  		b.Fatal(err)
  1654  	}
  1655  	benchState(sdb, b)
  1656  	if fileutil.FileExists(tp) && os.RemoveAll(tp) != nil {
  1657  		b.Error("Fail to remove testDB file")
  1658  	}
  1659  }
  1660  
  1661  func benchState(sf Factory, b *testing.B) {
  1662  	b.StopTimer()
  1663  	// set up
  1664  	accounts := []string{
  1665  		identityset.Address(28).String(),
  1666  		identityset.Address(29).String(),
  1667  		identityset.Address(30).String(),
  1668  		identityset.Address(31).String(),
  1669  		identityset.Address(32).String(),
  1670  		identityset.Address(33).String(),
  1671  	}
  1672  	pubKeys := []crypto.PublicKey{
  1673  		identityset.PrivateKey(28).PublicKey(),
  1674  		identityset.PrivateKey(29).PublicKey(),
  1675  		identityset.PrivateKey(30).PublicKey(),
  1676  		identityset.PrivateKey(31).PublicKey(),
  1677  		identityset.PrivateKey(32).PublicKey(),
  1678  		identityset.PrivateKey(33).PublicKey(),
  1679  	}
  1680  	nonces := make([]uint64, len(accounts))
  1681  	ge := genesis.Default
  1682  	prevHash := ge.Hash()
  1683  	for _, acc := range accounts {
  1684  		ge.InitBalanceMap[acc] = big.NewInt(int64(1000)).String()
  1685  	}
  1686  	acc := account.NewProtocol(rewarding.DepositGas)
  1687  	if err := sf.Register(acc); err != nil {
  1688  		b.Fatal(err)
  1689  	}
  1690  	ctx := genesis.WithGenesisContext(context.Background(), ge)
  1691  
  1692  	if err := sf.Start(ctx); err != nil {
  1693  		b.Fatal(err)
  1694  	}
  1695  	defer func() {
  1696  		if err := sf.Stop(ctx); err != nil {
  1697  			b.Fatal(err)
  1698  		}
  1699  	}()
  1700  
  1701  	gasLimit := testutil.TestGasLimit * 100000
  1702  
  1703  	total := 500
  1704  	acts := make([]*action.SealedEnvelope, 0, total)
  1705  	for numActs := 0; numActs < total; numActs++ {
  1706  		senderIdx := rand.Int() % len(accounts)
  1707  
  1708  		var chainIDBytes [4]byte
  1709  		enc.MachineEndian.PutUint32(chainIDBytes[:], 1)
  1710  		payload := []byte(randStringRunes(20))
  1711  		receiverAddr, err := address.FromBytes(payload)
  1712  		if err != nil {
  1713  			b.Fatal(err)
  1714  		}
  1715  		receiver := receiverAddr.String()
  1716  		nonces[senderIdx] += nonces[senderIdx]
  1717  		tx, err := action.NewTransfer(nonces[senderIdx], big.NewInt(1), receiver, nil, uint64(0), big.NewInt(0))
  1718  		if err != nil {
  1719  			b.Fatal(err)
  1720  		}
  1721  		bd := &action.EnvelopeBuilder{}
  1722  		elp := bd.SetNonce(nonces[senderIdx]).SetAction(tx).Build()
  1723  		selp := action.FakeSeal(elp, pubKeys[senderIdx])
  1724  		acts = append(acts, selp)
  1725  	}
  1726  	zctx := protocol.WithBlockCtx(context.Background(),
  1727  		protocol.BlockCtx{
  1728  			BlockHeight: uint64(1),
  1729  			Producer:    identityset.Address(27),
  1730  			GasLimit:    gasLimit,
  1731  		})
  1732  	zctx = genesis.WithGenesisContext(zctx, genesis.Default)
  1733  
  1734  	blk, err := block.NewTestingBuilder().
  1735  		SetHeight(uint64(1)).
  1736  		SetPrevBlockHash(prevHash).
  1737  		SetTimeStamp(testutil.TimestampNow()).
  1738  		AddActions(acts...).
  1739  		SignAndBuild(identityset.PrivateKey(27))
  1740  	if err != nil {
  1741  		b.Fatal(err)
  1742  	}
  1743  	if err := sf.PutBlock(zctx, &blk); err != nil {
  1744  		b.Fatal(err)
  1745  	}
  1746  
  1747  	// measure state read time
  1748  	for n := 1; n < b.N; n++ {
  1749  		b.StartTimer()
  1750  		idx := rand.Int() % len(accounts)
  1751  		addr, err := address.FromString(accounts[idx])
  1752  		if err != nil {
  1753  			b.Fatal(err)
  1754  		}
  1755  		_, err = accountutil.AccountState(zctx, sf, addr)
  1756  		if err != nil {
  1757  			b.Fatal(err)
  1758  		}
  1759  		b.StopTimer()
  1760  	}
  1761  }
  1762  
  1763  func init() {
  1764  	rand.Seed(time.Now().UnixNano())
  1765  }