package core import ( "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/consensus/engine" "github.com/harmony-one/harmony/consensus/reward" "github.com/harmony-one/harmony/core/rawdb" "github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" harmonyconfig "github.com/harmony-one/harmony/internal/configs/harmony" "github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/tikv/redis_helper" "github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/staking/slash" types2 "github.com/harmony-one/harmony/staking/types" ) // Options contains configuration values to change blockchain behaviour. type Options struct { // Subset of blockchain suitable for storing last epoch blocks i.e. blocks with shard state. EpochChain bool } // BlockChain represents the canonical chain given a database with a genesis // block. The Blockchain manages chain imports, reverts, chain reorganisations. // // Importing blocks in to the blockchain happens according to the set of rules // defined by the two stage validator. Processing of blocks is done using the // Processor which processes the included transaction. The validation of the state // is done in the second part of the validator. Failing results in aborting of // the import. // // The BlockChain also helps in returning blocks from **any** chain included // in the database as well as blocks that represents the canonical chain. It's // important to note that GetBlock can return any block and does not need to be // included in the canonical one where as GetBlockByNumber always represents the // canonical chain. type BlockChain interface { // ValidateNewBlock validates new block. ValidateNewBlock(block *types.Block, beaconChain BlockChain) error // SetHead rewinds the local chain to a new head. In the case of headers, everything // above the new head will be deleted and the new one set. In the case of blocks // though, the head may be further rewound if block bodies are missing (non-archive // nodes after a fast sync). SetHead(head uint64) error // ShardID returns the shard Id of the blockchain. ShardID() uint32 // CurrentBlock retrieves the current head block of the canonical chain. The // block is retrieved from the blockchain's internal cache. CurrentBlock() *types.Block // Validator returns the current validator. Validator() Validator // Processor returns the current processor. Processor() Processor // State returns a new mutable state based on the current HEAD block. State() (*state.DB, error) // StateAt returns a new mutable state based on a particular point in time. StateAt(root common.Hash) (*state.DB, error) // HasBlock checks if a block is fully present in the database or not. HasBlock(hash common.Hash, number uint64) bool // HasState checks if state trie is fully present in the database or not. HasState(hash common.Hash) bool // HasBlockAndState checks if a block and associated state trie is fully present // in the database or not, caching it if present. HasBlockAndState(hash common.Hash, number uint64) bool // GetBlock retrieves a block from the database by hash and number, // caching it if found. GetBlock(hash common.Hash, number uint64) *types.Block // GetBlockByHash retrieves a block from the database by hash, caching it if found. GetBlockByHash(hash common.Hash) *types.Block // GetBlockByNumber retrieves a block from the database by number, caching it // (associated with its hash) if found. GetBlockByNumber(number uint64) *types.Block // GetReceiptsByHash retrieves the receipts for all transactions in a given block. GetReceiptsByHash(hash common.Hash) types.Receipts // Stop stops the blockchain service. If any imports are currently in progress // it will abort them using the procInterrupt. Stop() // Rollback is designed to remove a chain of links from the database that aren't // certain enough to be valid. Rollback(chain []common.Hash) error // WriteBlockWithoutState writes only the block and its metadata to the database, // but does not write any state. This is used to construct competing side forks // up to the point where they exceed the canonical total difficulty. WriteBlockWithoutState(block *types.Block, td *big.Int) (err error) // WriteBlockWithState writes the block and all associated state to the database. WriteBlockWithState( block *types.Block, receipts []*types.Receipt, cxReceipts []*types.CXReceipt, stakeMsgs []types2.StakeMsg, paid reward.Reader, state *state.DB, ) (status WriteStatus, err error) // GetMaxGarbageCollectedBlockNumber .. GetMaxGarbageCollectedBlockNumber() int64 // InsertChain attempts to insert the given batch of blocks in to the canonical // chain or, otherwise, create a fork. If an error is returned it will return // the index number of the failing block as well an error describing what went // wrong. // // After insertion is done, all accumulated events will be fired. InsertChain(chain types.Blocks, verifyHeaders bool) (int, error) // BadBlocks returns a list of the last 'bad blocks' that // the client has seen on the network. BadBlocks() []BadBlock // CurrentHeader retrieves the current head header of the canonical chain. The // header is retrieved from the HeaderChain's internal cache. CurrentHeader() *block.Header // GetHeader retrieves a block header from the database by hash and number, // caching it if found. GetHeader(hash common.Hash, number uint64) *block.Header // GetHeaderByHash retrieves a block header from the database by hash, caching it if // found. GetHeaderByHash(hash common.Hash) *block.Header // GetCanonicalHash returns the canonical hash for a given block number. GetCanonicalHash(number uint64) common.Hash // GetHeaderByNumber retrieves a block header from the database by number, // caching it (associated with its hash) if found. GetHeaderByNumber(number uint64) *block.Header // Config retrieves the blockchain's chain configuration. Config() *params.ChainConfig // Engine retrieves the blockchain's consensus engine. Engine() engine.Engine // SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent. SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription // SubscribeTraceEvent registers a subscription of ChainEvent. SubscribeTraceEvent(ch chan<- TraceEvent) event.Subscription // SubscribeChainEvent registers a subscription of ChainEvent. SubscribeChainEvent(ch chan<- ChainEvent) event.Subscription // SubscribeChainHeadEvent registers a subscription of ChainHeadEvent. SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription // SubscribeChainSideEvent registers a subscription of ChainSideEvent. SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription // SubscribeLogsEvent registers a subscription of []*types.Log. SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription // ReadShardState retrieves sharding state given the epoch number. ReadShardState(epoch *big.Int) (*shard.State, error) // WriteShardStateBytes saves the given sharding state under the given epoch number. WriteShardStateBytes(db rawdb.DatabaseWriter, epoch *big.Int, shardState []byte, ) (*shard.State, error) // WriteHeadBlock writes head block. WriteHeadBlock(block *types.Block) error // ReadCommitSig retrieves the commit signature on a block. ReadCommitSig(blockNum uint64) ([]byte, error) // WriteCommitSig saves the commits signatures signed on a block. WriteCommitSig(blockNum uint64, lastCommits []byte) error // GetVdfByNumber retrieves the rand seed given the block number, return 0 if not exist. GetVdfByNumber(number uint64) []byte // GetVrfByNumber retrieves the randomness preimage given the block number, return 0 if not exist GetVrfByNumber(number uint64) []byte // ChainDb returns the database. ChainDb() ethdb.Database // GetEpochBlockNumber returns the first block number of the given epoch. GetEpochBlockNumber(epoch *big.Int) (*big.Int, error) // StoreEpochBlockNumber stores the given epoch-first block number. StoreEpochBlockNumber( epoch *big.Int, blockNum *big.Int, ) error // ReadEpochVrfBlockNums retrieves block numbers with valid VRF for the specified epoch. ReadEpochVrfBlockNums(epoch *big.Int) ([]uint64, error) // WriteEpochVrfBlockNums saves block numbers with valid VRF for the specified epoch. WriteEpochVrfBlockNums(epoch *big.Int, vrfNumbers []uint64) error // ReadEpochVdfBlockNum retrieves block number with valid VDF for the specified epoch. ReadEpochVdfBlockNum(epoch *big.Int) (*big.Int, error) // WriteEpochVdfBlockNum saves block number with valid VDF for the specified epoch. WriteEpochVdfBlockNum(epoch *big.Int, blockNum *big.Int) error // WriteCrossLinks saves the hashes of crosslinks by shardID and blockNum combination key. WriteCrossLinks(batch rawdb.DatabaseWriter, cls []types.CrossLink) error // DeleteCrossLinks removes the hashes of crosslinks by shardID and blockNum combination key. DeleteCrossLinks(cls []types.CrossLink) error // ReadCrossLink retrieves crosslink given shardID and blockNum. ReadCrossLink(shardID uint32, blockNum uint64) (*types.CrossLink, error) // LastContinuousCrossLink saves the last crosslink of a shard // This function will update the latest crosslink in the sense that // any previous block's crosslink is received up to this point // there is no missing hole between genesis to this crosslink of given shardID. LastContinuousCrossLink(batch rawdb.DatabaseWriter, shardID uint32) error // ReadShardLastCrossLink retrieves the last crosslink of a shard. ReadShardLastCrossLink(shardID uint32) (*types.CrossLink, error) // DeleteFromPendingSlashingCandidates .. DeleteFromPendingSlashingCandidates( processed slash.Records, ) error // ReadPendingSlashingCandidates retrieves pending slashing candidates. ReadPendingSlashingCandidates() slash.Records // ReadPendingCrossLinks retrieves pending crosslinks. ReadPendingCrossLinks() ([]types.CrossLink, error) // CachePendingCrossLinks caches the pending crosslinks in memory. CachePendingCrossLinks(crossLinks []types.CrossLink) error // SavePendingCrossLinks saves the pending crosslinks in db. SavePendingCrossLinks() error // AddPendingSlashingCandidates appends pending slashing candidates. AddPendingSlashingCandidates( candidates slash.Records, ) error // AddPendingCrossLinks appends pending crosslinks. AddPendingCrossLinks(pendingCLs []types.CrossLink) (int, error) // DeleteFromPendingCrossLinks delete pending crosslinks that already committed (i.e. passed in the params). DeleteFromPendingCrossLinks(crossLinks []types.CrossLink) (int, error) // IsSameLeaderAsPreviousBlock retrieves a block from the database by number, caching it. IsSameLeaderAsPreviousBlock(block *types.Block) bool // GetVMConfig returns the blockchain VM config. GetVMConfig() *vm.Config // ReadCXReceipts retrieves the cross shard transaction receipts of a given shard. ReadCXReceipts(shardID uint32, blockNum uint64, blockHash common.Hash) (types.CXReceipts, error) // CXMerkleProof calculates the cross shard transaction merkle proof of a given destination shard. CXMerkleProof(toShardID uint32, block *types.Block) (*types.CXMerkleProof, error) // WriteCXReceiptsProofSpent mark the CXReceiptsProof list with given unspent status WriteCXReceiptsProofSpent(db rawdb.DatabaseWriter, cxps []*types.CXReceiptsProof) error // IsSpent checks whether a CXReceiptsProof is spent. IsSpent(cxp *types.CXReceiptsProof) bool // ReadTxLookupEntry returns where the given transaction resides in the chain, // as a (block hash, block number, index in transaction list) triple. // returns 0, 0 if not found. ReadTxLookupEntry(txID common.Hash) (common.Hash, uint64, uint64) // ReadValidatorInformationAtRoot reads staking // information of given validatorWrapper at a specific state root. ReadValidatorInformationAtRoot( addr common.Address, root common.Hash, ) (*types2.ValidatorWrapper, error) // ReadValidatorInformationAtState reads staking // information of given validatorWrapper at a specific state root. ReadValidatorInformationAtState( addr common.Address, state *state.DB, ) (*types2.ValidatorWrapper, error) // ReadValidatorInformation reads staking information of given validator address. ReadValidatorInformation( addr common.Address, ) (*types2.ValidatorWrapper, error) // ReadValidatorSnapshotAtEpoch reads the snapshot // staking validator information of given validator address. ReadValidatorSnapshotAtEpoch( epoch *big.Int, addr common.Address, ) (*types2.ValidatorSnapshot, error) // ReadValidatorSnapshot reads the snapshot staking information of given validator address. ReadValidatorSnapshot( addr common.Address, ) (*types2.ValidatorSnapshot, error) // WriteValidatorSnapshot writes the snapshot of provided validator. WriteValidatorSnapshot( batch rawdb.DatabaseWriter, snapshot *types2.ValidatorSnapshot, ) error // ReadValidatorStats reads the stats of a validator. ReadValidatorStats( addr common.Address, ) (*types2.ValidatorStats, error) // UpdateValidatorVotingPower writes the voting power for the committees. UpdateValidatorVotingPower( batch rawdb.DatabaseWriter, block *types.Block, newEpochSuperCommittee, currentEpochSuperCommittee *shard.State, state *state.DB, ) (map[common.Address]*types2.ValidatorStats, error) // ComputeAndUpdateAPR ... ComputeAndUpdateAPR( block *types.Block, now *big.Int, wrapper *types2.ValidatorWrapper, stats *types2.ValidatorStats, ) error // UpdateValidatorSnapshots updates the content snapshot of all validators // Note: this should only be called within the blockchain insert process. UpdateValidatorSnapshots( batch rawdb.DatabaseWriter, epoch *big.Int, state *state.DB, newValidators []common.Address, ) error // ReadValidatorList reads the addresses of current all validators. ReadValidatorList() ([]common.Address, error) // WriteValidatorList writes the list of validator addresses to database // Note: this should only be called within the blockchain insert process. WriteValidatorList( db rawdb.DatabaseWriter, addrs []common.Address, ) error // ReadDelegationsByDelegator reads the addresses of validators delegated by a delegator. ReadDelegationsByDelegator( delegator common.Address, ) (m types2.DelegationIndexes, err error) // ReadDelegationsByDelegatorAt reads the addresses of validators delegated by a delegator at a given block. ReadDelegationsByDelegatorAt( delegator common.Address, blockNum *big.Int, ) (m types2.DelegationIndexes, err error) // UpdateStakingMetaData updates the metadata of validators and delegations, // including the full validator list and delegation indexes. // Note: this should only be called within the blockchain insert process. UpdateStakingMetaData( batch rawdb.DatabaseWriter, block *types.Block, stakeMsgs []types2.StakeMsg, state *state.DB, epoch, newEpoch *big.Int, ) (newValidators []common.Address, err error) // ReadBlockRewardAccumulator must only be called on beaconchain // Note that block rewards are only for staking era. ReadBlockRewardAccumulator(number uint64) (*big.Int, error) // WriteBlockRewardAccumulator directly writes the BlockRewardAccumulator value // Note: this should only be called once during staking launch. WriteBlockRewardAccumulator( batch rawdb.DatabaseWriter, reward *big.Int, number uint64, ) error // UpdateBlockRewardAccumulator .. // Note: this should only be called within the blockchain insert process. UpdateBlockRewardAccumulator( batch rawdb.DatabaseWriter, diff *big.Int, number uint64, ) error // ValidatorCandidates returns the up to date validator candidates for next epoch. ValidatorCandidates() []common.Address // DelegatorsInformation returns up to date information of delegators of a given validator address. DelegatorsInformation(addr common.Address) []*types2.Delegation // GetECDSAFromCoinbase retrieve corresponding ecdsa address from Coinbase Address. GetECDSAFromCoinbase(header *block.Header) (common.Address, error) // SuperCommitteeForNextEpoch ... // isVerify=true means validators use it to verify // isVerify=false means leader is to propose. SuperCommitteeForNextEpoch( beacon engine.ChainReader, header *block.Header, isVerify bool, ) (*shard.State, error) // EnablePruneBeaconChainFeature enabled prune BeaconChain feature. EnablePruneBeaconChainFeature() // IsEnablePruneBeaconChainFeature returns is enable prune BeaconChain feature. IsEnablePruneBeaconChainFeature() bool // CommitOffChainData write off chain data of a block onto db writer. CommitOffChainData( batch rawdb.DatabaseWriter, block *types.Block, receipts []*types.Receipt, cxReceipts []*types.CXReceipt, stakeMsgs []types2.StakeMsg, payout reward.Reader, state *state.DB, ) (status WriteStatus, err error) // ========== Only For Tikv Start ========== // return true if is tikv writer master IsTikvWriterMaster() bool // RedisPreempt used for tikv mode, get the redis preempt instance RedisPreempt() *redis_helper.RedisPreempt // SyncFromTiKVWriter used for tikv mode, all reader or follower writer used to sync block from master writer SyncFromTiKVWriter(newBlkNum uint64, logs []*types.Log) error // InitTiKV used for tikv mode, init the tikv mode InitTiKV(conf *harmonyconfig.TiKVConfig) // ========== Only For Tikv End ========== }