WriteBlockWithState writes the block and all associated state to the database.
(block *types.Block, pubReceipts []*types.Receipt, privReceipts []*types.Receipt, pubState *state.StateDB, privState *state.StateDB)
| 1051 | |
| 1052 | // WriteBlockWithState writes the block and all associated state to the database. |
| 1053 | func (bc *BlockChain) WriteBlockWithState(block *types.Block, pubReceipts []*types.Receipt, privReceipts []*types.Receipt, |
| 1054 | pubState *state.StateDB, privState *state.StateDB) (status WriteStatus, err error) { |
| 1055 | bc.wg.Add(1) |
| 1056 | defer bc.wg.Done() |
| 1057 | |
| 1058 | // Make sure no inconsistent pubState is leaked during insertion |
| 1059 | bc.mu.Lock() |
| 1060 | defer bc.mu.Unlock() |
| 1061 | |
| 1062 | // Write other block data using a batch. |
| 1063 | batch := bc.db.NewBatch() |
| 1064 | rawdb.WriteBlock(batch, block) |
| 1065 | |
| 1066 | root, err := pubState.Commit(true) |
| 1067 | if err != nil { |
| 1068 | return NonStatTy, err |
| 1069 | } |
| 1070 | // write private transaction |
| 1071 | privStateRoot, err := privState.Commit(true) |
| 1072 | if err != nil { |
| 1073 | return NonStatTy, err |
| 1074 | } |
| 1075 | err = WritePrivateStateRoot(bc.db, block.StateRoot(), privStateRoot) |
| 1076 | if err != nil { |
| 1077 | return NonStatTy, err |
| 1078 | } |
| 1079 | |
| 1080 | triedb := bc.stateCache.TrieDB() |
| 1081 | // If we're running an archive node, always flush |
| 1082 | disabled := bc.cacheConfig.Disabled |
| 1083 | // commit root to the trie immediately! |
| 1084 | disabled = true |
| 1085 | if disabled { |
| 1086 | if err := triedb.Commit(root, false); err != nil { |
| 1087 | return NonStatTy, err |
| 1088 | } |
| 1089 | } else { |
| 1090 | // Full but not archive node, do proper garbage collection |
| 1091 | triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive |
| 1092 | bc.triegc.Push(root, -float32(block.NumberU64())) |
| 1093 | |
| 1094 | if current := block.NumberU64(); current > triesInMemory { |
| 1095 | // If we exceeded our memory allowance, flush matured singleton nodes to disk |
| 1096 | var ( |
| 1097 | nodes, imgs = triedb.Size() |
| 1098 | limit = common.StorageSize(bc.cacheConfig.TrieNodeLimit) * 1024 * 1024 |
| 1099 | ) |
| 1100 | if nodes > limit || imgs > 4*1024*1024 { |
| 1101 | triedb.Cap(limit - database.IdealBatchSize) |
| 1102 | } |
| 1103 | // Find the next pubState trie we need to commit |
| 1104 | header := bc.GetHeaderByNumber(current - triesInMemory) |
| 1105 | chosen := header.Number.Uint64() |
| 1106 | |
| 1107 | // If we exceeded out time allowance, flush an entire trie to disk |
| 1108 | if bc.gcproc > bc.cacheConfig.TrieTimeLimit { |
| 1109 | // If we're exceeding limits but haven't reached a large enough memory gap, |
| 1110 | // warn the user that the system is becoming unstable. |
no test coverage detected