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 }