-
Notifications
You must be signed in to change notification settings - Fork 2
/
blockchain.go
349 lines (342 loc) · 17.3 KB
/
blockchain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
package core
import (
"math/big"
"github.com/PositionExchange/posichain/block"
"github.com/PositionExchange/posichain/consensus/engine"
"github.com/PositionExchange/posichain/consensus/reward"
"github.com/PositionExchange/posichain/core/rawdb"
"github.com/PositionExchange/posichain/core/state"
"github.com/PositionExchange/posichain/core/types"
"github.com/PositionExchange/posichain/core/vm"
harmonyconfig "github.com/PositionExchange/posichain/internal/configs/harmony"
"github.com/PositionExchange/posichain/internal/params"
"github.com/PositionExchange/posichain/internal/tikv/redis_helper"
"github.com/PositionExchange/posichain/shard"
"github.com/PositionExchange/posichain/staking/slash"
types2 "github.com/PositionExchange/posichain/staking/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
)
// 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 ==========
}