github.com/iotexproject/iotex-core@v1.14.1-rc1/state/factory/util.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  
    11  	"github.com/iotexproject/go-pkgs/bloom"
    12  	"github.com/iotexproject/go-pkgs/crypto"
    13  	"github.com/iotexproject/go-pkgs/hash"
    14  	"github.com/pkg/errors"
    15  
    16  	"github.com/iotexproject/iotex-core/action"
    17  	"github.com/iotexproject/iotex-core/action/protocol"
    18  	"github.com/iotexproject/iotex-core/blockchain/block"
    19  	"github.com/iotexproject/iotex-core/blockchain/genesis"
    20  	"github.com/iotexproject/iotex-core/db"
    21  	"github.com/iotexproject/iotex-core/db/trie"
    22  	"github.com/iotexproject/iotex-core/db/trie/mptrie"
    23  	"github.com/iotexproject/iotex-core/state"
    24  )
    25  
    26  func processOptions(opts ...protocol.StateOption) (*protocol.StateConfig, error) {
    27  	cfg, err := protocol.CreateStateConfig(opts...)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	if len(cfg.Namespace) == 0 {
    32  		cfg.Namespace = AccountKVNamespace
    33  	}
    34  	return cfg, nil
    35  }
    36  
    37  func appendActionIndex(accountNonceMap map[string][]uint64, srcAddr string, nonce uint64) {
    38  	if nonce == 0 {
    39  		return
    40  	}
    41  	if _, ok := accountNonceMap[srcAddr]; !ok {
    42  		accountNonceMap[srcAddr] = make([]uint64, 0)
    43  	}
    44  	accountNonceMap[srcAddr] = append(accountNonceMap[srcAddr], nonce)
    45  }
    46  
    47  func calculateReceiptRoot(receipts []*action.Receipt) hash.Hash256 {
    48  	if len(receipts) == 0 {
    49  		return hash.ZeroHash256
    50  	}
    51  	h := make([]hash.Hash256, 0, len(receipts))
    52  	for _, receipt := range receipts {
    53  		h = append(h, receipt.Hash())
    54  	}
    55  	res := crypto.NewMerkleTree(h).HashTree()
    56  	return res
    57  }
    58  
    59  func calculateLogsBloom(ctx context.Context, receipts []*action.Receipt) bloom.BloomFilter {
    60  	blkCtx := protocol.MustGetBlockCtx(ctx)
    61  	g := genesis.MustExtractGenesisContext(ctx)
    62  	if blkCtx.BlockHeight < g.AleutianBlockHeight {
    63  		return nil
    64  	}
    65  	// block-level bloom filter used legacy implementation
    66  	bloom, _ := bloom.NewBloomFilterLegacy(2048, 3)
    67  	for _, receipt := range receipts {
    68  		for _, l := range receipt.Logs() {
    69  			for _, topic := range l.Topics {
    70  				bloom.Add(topic[:])
    71  			}
    72  		}
    73  	}
    74  	return bloom
    75  }
    76  
    77  // generateWorkingSetCacheKey generates hash key for workingset cache by hashing blockheader core and producer pubkey
    78  func generateWorkingSetCacheKey(blkHeader block.Header, producerAddr string) hash.Hash256 {
    79  	sum := append(blkHeader.SerializeCore(), []byte(producerAddr)...)
    80  	return hash.Hash256b(sum)
    81  }
    82  
    83  func protocolPreCommit(ctx context.Context, sr protocol.StateManager) error {
    84  	if reg, ok := protocol.GetRegistry(ctx); ok {
    85  		for _, p := range reg.All() {
    86  			post, ok := p.(protocol.PreCommitter)
    87  			if ok && sr.ProtocolDirty(p.Name()) {
    88  				if err := post.PreCommit(ctx, sr); err != nil {
    89  					return err
    90  				}
    91  			}
    92  		}
    93  	}
    94  	return nil
    95  }
    96  
    97  func protocolCommit(ctx context.Context, sr protocol.StateManager) error {
    98  	if reg, ok := protocol.GetRegistry(ctx); ok {
    99  		for _, p := range reg.All() {
   100  			post, ok := p.(protocol.Committer)
   101  			if ok && sr.ProtocolDirty(p.Name()) {
   102  				if err := post.Commit(ctx, sr); err != nil {
   103  					return err
   104  				}
   105  			}
   106  		}
   107  	}
   108  	return nil
   109  }
   110  
   111  func readStates(kvStore db.KVStore, namespace string, keys [][]byte) ([][]byte, error) {
   112  	if keys == nil {
   113  		_, values, err := kvStore.Filter(namespace, func(k, v []byte) bool { return true }, nil, nil)
   114  		if err != nil {
   115  			if errors.Cause(err) == db.ErrNotExist || errors.Cause(err) == db.ErrBucketNotExist {
   116  				return nil, errors.Wrapf(state.ErrStateNotExist, "failed to get states of ns = %x", namespace)
   117  			}
   118  			return nil, err
   119  		}
   120  		return values, nil
   121  	}
   122  	var values [][]byte
   123  	for _, key := range keys {
   124  		value, err := kvStore.Get(namespace, key)
   125  		switch errors.Cause(err) {
   126  		case db.ErrNotExist, db.ErrBucketNotExist:
   127  			values = append(values, nil)
   128  		case nil:
   129  			values = append(values, value)
   130  		default:
   131  			return nil, err
   132  		}
   133  	}
   134  	return values, nil
   135  }
   136  
   137  func newTwoLayerTrie(ns string, dao db.KVStore, rootKey string, create bool) (trie.TwoLayerTrie, error) {
   138  	dbForTrie, err := trie.NewKVStore(ns, dao)
   139  	if err != nil {
   140  		return nil, errors.Wrap(err, "failed to create db for trie")
   141  	}
   142  	_, err = dbForTrie.Get([]byte(rootKey))
   143  	switch errors.Cause(err) {
   144  	case trie.ErrNotExist:
   145  		if !create {
   146  			return nil, err
   147  		}
   148  	case nil:
   149  		break
   150  	default:
   151  		return nil, err
   152  	}
   153  	return mptrie.NewTwoLayerTrie(dbForTrie, rootKey), nil
   154  }