Refactor offchain data commit; Make block onchain/offchain commit atomic (#2279)
* Refactor offchain data; Add epoch to ValidatorSnapshot * Make block onchain/offchain data commit atomicallypull/2253/head
parent
06a967f73a
commit
9ffbf682c0
@ -0,0 +1,184 @@ |
||||
package core |
||||
|
||||
import ( |
||||
"errors" |
||||
"math/big" |
||||
|
||||
"github.com/ethereum/go-ethereum/common" |
||||
"github.com/ethereum/go-ethereum/rlp" |
||||
"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/internal/utils" |
||||
"github.com/harmony-one/harmony/shard" |
||||
) |
||||
|
||||
// CommitOffChainData write off chain data of a block onto db writer.
|
||||
func (bc *BlockChain) CommitOffChainData( |
||||
batch rawdb.DatabaseWriter, block *types.Block, receipts []*types.Receipt, |
||||
cxReceipts []*types.CXReceipt, payout *big.Int, state *state.DB, root common.Hash) (status WriteStatus, err error) { |
||||
//// Write receipts of the block
|
||||
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receipts) |
||||
|
||||
//// Cross-shard txns
|
||||
epoch := block.Header().Epoch() |
||||
if bc.chainConfig.HasCrossTxFields(block.Epoch()) { |
||||
shardingConfig := shard.Schedule.InstanceForEpoch(epoch) |
||||
shardNum := int(shardingConfig.NumShards()) |
||||
for i := 0; i < shardNum; i++ { |
||||
if i == int(block.ShardID()) { |
||||
continue |
||||
} |
||||
|
||||
shardReceipts := types.CXReceipts(cxReceipts).GetToShardReceipts(uint32(i)) |
||||
err := rawdb.WriteCXReceipts(batch, uint32(i), block.NumberU64(), block.Hash(), shardReceipts) |
||||
if err != nil { |
||||
utils.Logger().Error().Err(err).Interface("shardReceipts", shardReceipts).Int("toShardID", i).Msg("WriteCXReceipts cannot write into database") |
||||
return NonStatTy, err |
||||
} |
||||
} |
||||
// Mark incomingReceipts in the block as spent
|
||||
bc.WriteCXReceiptsProofSpent(batch, block.IncomingReceipts()) |
||||
} |
||||
|
||||
//// VRF + VDF
|
||||
//check non zero VRF field in header and add to local db
|
||||
//if len(block.Vrf()) > 0 {
|
||||
// vrfBlockNumbers, _ := bc.ReadEpochVrfBlockNums(block.Header().Epoch())
|
||||
// if (len(vrfBlockNumbers) > 0) && (vrfBlockNumbers[len(vrfBlockNumbers)-1] == block.NumberU64()) {
|
||||
// utils.Logger().Error().
|
||||
// Str("number", block.Number().String()).
|
||||
// Str("epoch", block.Header().Epoch().String()).
|
||||
// Msg("VRF block number is already in local db")
|
||||
// } else {
|
||||
// vrfBlockNumbers = append(vrfBlockNumbers, block.NumberU64())
|
||||
// err = bc.WriteEpochVrfBlockNums(block.Header().Epoch(), vrfBlockNumbers)
|
||||
// if err != nil {
|
||||
// utils.Logger().Error().
|
||||
// Str("number", block.Number().String()).
|
||||
// Str("epoch", block.Header().Epoch().String()).
|
||||
// Msg("failed to write VRF block number to local db")
|
||||
// return NonStatTy, err
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
////check non zero Vdf in header and add to local db
|
||||
//if len(block.Vdf()) > 0 {
|
||||
// err = bc.WriteEpochVdfBlockNum(block.Header().Epoch(), block.Number())
|
||||
// if err != nil {
|
||||
// utils.Logger().Error().
|
||||
// Str("number", block.Number().String()).
|
||||
// Str("epoch", block.Header().Epoch().String()).
|
||||
// Msg("failed to write VDF block number to local db")
|
||||
// return NonStatTy, err
|
||||
// }
|
||||
//}
|
||||
|
||||
//// Shard State and Validator Update
|
||||
header := block.Header() |
||||
if len(header.ShardState()) > 0 { |
||||
// Write shard state for the new epoch
|
||||
epoch := new(big.Int).Add(header.Epoch(), common.Big1) |
||||
shardState, err := block.Header().GetShardState() |
||||
if err == nil && shardState.Epoch != nil && bc.chainConfig.IsStaking(shardState.Epoch) { |
||||
// After staking, the epoch will be decided by the epoch in the shard state.
|
||||
epoch = new(big.Int).Set(shardState.Epoch) |
||||
} |
||||
|
||||
newShardState, err := bc.WriteShardStateBytes(batch, epoch, header.ShardState()) |
||||
if err != nil { |
||||
header.Logger(utils.Logger()).Warn().Err(err).Msg("cannot store shard state") |
||||
return NonStatTy, err |
||||
} |
||||
|
||||
// Find all the active validator addresses and store them in db
|
||||
allActiveValidators := []common.Address{} |
||||
processed := make(map[common.Address]struct{}) |
||||
for i := range newShardState.Shards { |
||||
shard := newShardState.Shards[i] |
||||
for j := range shard.Slots { |
||||
slot := shard.Slots[j] |
||||
if slot.EffectiveStake != nil { // For external validator
|
||||
_, ok := processed[slot.EcdsaAddress] |
||||
if !ok { |
||||
processed[slot.EcdsaAddress] = struct{}{} |
||||
allActiveValidators = append(allActiveValidators, shard.Slots[j].EcdsaAddress) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Update active validators
|
||||
if err := bc.WriteActiveValidatorList(batch, allActiveValidators); err != nil { |
||||
return NonStatTy, err |
||||
} |
||||
|
||||
// Update snapshots for all validators
|
||||
if err := bc.UpdateValidatorSnapshots(batch, epoch); err != nil { |
||||
return NonStatTy, err |
||||
} |
||||
} |
||||
|
||||
// Do bookkeeping for new staking txns
|
||||
for _, tx := range block.StakingTransactions() { |
||||
err = bc.UpdateStakingMetaData(batch, tx, root) |
||||
// keep offchain database consistency with onchain we need revert
|
||||
// but it should not happend unless local database corrupted
|
||||
if err != nil { |
||||
utils.Logger().Debug().Msgf("oops, UpdateStakingMetaData failed, err: %+v", err) |
||||
return NonStatTy, err |
||||
} |
||||
} |
||||
|
||||
// Update voting power of validators for all shards
|
||||
if block.ShardID() == shard.BeaconChainShardID && |
||||
len(block.Header().ShardState()) > 0 { |
||||
shardState := new(shard.State) |
||||
|
||||
if shardState, err = shard.DecodeWrapper(block.Header().ShardState()); err == nil { |
||||
if err = bc.UpdateValidatorVotingPower(batch, shardState); err != nil { |
||||
utils.Logger().Err(err).Msg("[UpdateValidatorVotingPower] Failed to update voting power") |
||||
} |
||||
} else { |
||||
utils.Logger().Err(err).Msg("[UpdateValidatorVotingPower] Failed to decode shard state") |
||||
} |
||||
} |
||||
|
||||
//// Writing beacon chain cross links
|
||||
if header.ShardID() == shard.BeaconChainShardID && |
||||
bc.chainConfig.IsCrossLink(block.Epoch()) && |
||||
len(header.CrossLinks()) > 0 { |
||||
crossLinks := &types.CrossLinks{} |
||||
err = rlp.DecodeBytes(header.CrossLinks(), crossLinks) |
||||
if err != nil { |
||||
header.Logger(utils.Logger()).Warn().Err(err).Msg("[insertChain/crosslinks] cannot parse cross links") |
||||
return NonStatTy, err |
||||
} |
||||
if !crossLinks.IsSorted() { |
||||
header.Logger(utils.Logger()).Warn().Err(err).Msg("[insertChain/crosslinks] cross links are not sorted") |
||||
return NonStatTy, errors.New("proposed cross links are not sorted") |
||||
} |
||||
for _, crossLink := range *crossLinks { |
||||
// Process crosslink
|
||||
if err := bc.WriteCrossLinks(batch, types.CrossLinks{crossLink}); err == nil { |
||||
utils.Logger().Info().Uint64("blockNum", crossLink.BlockNum()).Uint32("shardID", crossLink.ShardID()).Msg("[insertChain/crosslinks] Cross Link Added to Beaconchain") |
||||
} |
||||
bc.LastContinuousCrossLink(batch, crossLink) |
||||
} |
||||
|
||||
//clean/update local database cache after crosslink inserted into blockchain
|
||||
num, err := bc.DeleteCommittedFromPendingCrossLinks(*crossLinks) |
||||
utils.Logger().Debug().Msgf("DeleteCommittedFromPendingCrossLinks, crosslinks in header %d, pending crosslinks: %d, error: %+v", len(*crossLinks), num, err) |
||||
} |
||||
|
||||
if bc.CurrentHeader().ShardID() == shard.BeaconChainShardID { |
||||
if bc.chainConfig.IsStaking(block.Epoch()) { |
||||
bc.UpdateBlockRewardAccumulator(batch, payout, block.Number().Uint64()) |
||||
} else { |
||||
// block reward never accumulate before staking
|
||||
bc.WriteBlockRewardAccumulator(batch, big.NewInt(0), block.Number().Uint64()) |
||||
} |
||||
} |
||||
return CanonStatTy, nil |
||||
} |
@ -0,0 +1,362 @@ |
||||
package rawdb |
||||
|
||||
import ( |
||||
"math/big" |
||||
|
||||
"github.com/ethereum/go-ethereum/common" |
||||
"github.com/ethereum/go-ethereum/rlp" |
||||
"github.com/harmony-one/harmony/core/types" |
||||
"github.com/harmony-one/harmony/internal/ctxerror" |
||||
"github.com/harmony-one/harmony/internal/utils" |
||||
"github.com/harmony-one/harmony/shard" |
||||
staking "github.com/harmony-one/harmony/staking/types" |
||||
) |
||||
|
||||
// ReadShardState retrieves shard state of a specific epoch.
|
||||
func ReadShardState( |
||||
db DatabaseReader, epoch *big.Int, |
||||
) (*shard.State, error) { |
||||
data, err := db.Get(shardStateKey(epoch)) |
||||
if err != nil { |
||||
return nil, ctxerror.New(MsgNoShardStateFromDB, |
||||
"epoch", epoch, |
||||
).WithCause(err) |
||||
} |
||||
ss, err2 := shard.DecodeWrapper(data) |
||||
if err2 != nil { |
||||
return nil, ctxerror.New("cannot decode sharding state", |
||||
"epoch", epoch, |
||||
).WithCause(err2) |
||||
} |
||||
return ss, nil |
||||
} |
||||
|
||||
// WriteShardStateBytes stores sharding state into database.
|
||||
func WriteShardStateBytes(db DatabaseWriter, epoch *big.Int, data []byte) (err error) { |
||||
if err = db.Put(shardStateKey(epoch), data); err != nil { |
||||
return ctxerror.New("cannot write sharding state", |
||||
"epoch", epoch, |
||||
).WithCause(err) |
||||
} |
||||
utils.Logger().Info().Str("epoch", epoch.String()).Int("size", len(data)).Msg("wrote sharding state") |
||||
return nil |
||||
} |
||||
|
||||
// ReadLastCommits retrieves the commit signatures on the current block of blockchain.
|
||||
func ReadLastCommits(db DatabaseReader) ([]byte, error) { |
||||
var data []byte |
||||
data, err := db.Get(lastCommitsKey) |
||||
if err != nil { |
||||
return nil, ctxerror.New("cannot read last commits from rawdb").WithCause(err) |
||||
} |
||||
return data, nil |
||||
} |
||||
|
||||
// WriteLastCommits stores the commit signatures collected on the newly confirmed block into database.
|
||||
func WriteLastCommits( |
||||
db DatabaseWriter, data []byte, |
||||
) (err error) { |
||||
if err = db.Put(lastCommitsKey, data); err != nil { |
||||
return ctxerror.New("cannot write last commits").WithCause(err) |
||||
} |
||||
utils.Logger().Info(). |
||||
Int("size", len(data)). |
||||
Msg("wrote last commits") |
||||
return nil |
||||
} |
||||
|
||||
// ReadCrossLinkShardBlock retrieves the blockHash given shardID and blockNum
|
||||
func ReadCrossLinkShardBlock(db DatabaseReader, shardID uint32, blockNum uint64) ([]byte, error) { |
||||
return db.Get(crosslinkKey(shardID, blockNum)) |
||||
} |
||||
|
||||
// WriteCrossLinkShardBlock stores the blockHash given shardID and blockNum
|
||||
func WriteCrossLinkShardBlock(db DatabaseWriter, shardID uint32, blockNum uint64, data []byte) error { |
||||
return db.Put(crosslinkKey(shardID, blockNum), data) |
||||
} |
||||
|
||||
// DeleteCrossLinkShardBlock deletes the blockHash given shardID and blockNum
|
||||
func DeleteCrossLinkShardBlock(db DatabaseDeleter, shardID uint32, blockNum uint64) error { |
||||
return db.Delete(crosslinkKey(shardID, blockNum)) |
||||
} |
||||
|
||||
// ReadShardLastCrossLink read the last cross link of a shard
|
||||
func ReadShardLastCrossLink(db DatabaseReader, shardID uint32) ([]byte, error) { |
||||
return db.Get(shardLastCrosslinkKey(shardID)) |
||||
} |
||||
|
||||
// WriteShardLastCrossLink stores the last cross link of a shard
|
||||
func WriteShardLastCrossLink(db DatabaseWriter, shardID uint32, data []byte) error { |
||||
return db.Put(shardLastCrosslinkKey(shardID), data) |
||||
} |
||||
|
||||
// ReadPendingCrossLinks retrieves last pending crosslinks.
|
||||
func ReadPendingCrossLinks(db DatabaseReader) ([]byte, error) { |
||||
return db.Get(pendingCrosslinkKey) |
||||
} |
||||
|
||||
// WritePendingCrossLinks stores last pending crosslinks into database.
|
||||
func WritePendingCrossLinks(db DatabaseWriter, bytes []byte) error { |
||||
return db.Put(pendingCrosslinkKey, bytes) |
||||
} |
||||
|
||||
// DeletePendingCrossLinks stores last pending crosslinks into database.
|
||||
func DeletePendingCrossLinks(db DatabaseDeleter) error { |
||||
return db.Delete(pendingCrosslinkKey) |
||||
} |
||||
|
||||
// ReadPendingSlashingCandidates retrieves last pending slashing candidates
|
||||
func ReadPendingSlashingCandidates(db DatabaseReader) ([]byte, error) { |
||||
return db.Get(pendingSlashingKey) |
||||
} |
||||
|
||||
// WritePendingSlashingCandidates stores last pending slashing candidates into database.
|
||||
func WritePendingSlashingCandidates(db DatabaseWriter, bytes []byte) error { |
||||
return db.Put(pendingSlashingKey, bytes) |
||||
} |
||||
|
||||
// DeletePendingSlashingCandidates stores last pending slashing candidates into database.
|
||||
func DeletePendingSlashingCandidates(db DatabaseDeleter) error { |
||||
return db.Delete(pendingSlashingKey) |
||||
} |
||||
|
||||
// ReadCXReceipts retrieves all the transactions of receipts given destination shardID, number and blockHash
|
||||
func ReadCXReceipts(db DatabaseReader, shardID uint32, number uint64, hash common.Hash) (types.CXReceipts, error) { |
||||
data, err := db.Get(cxReceiptKey(shardID, number, hash)) |
||||
if err != nil || len(data) == 0 { |
||||
utils.Logger().Info().Err(err).Uint64("number", number).Int("dataLen", len(data)).Msg("ReadCXReceipts") |
||||
return nil, err |
||||
} |
||||
cxReceipts := types.CXReceipts{} |
||||
if err := rlp.DecodeBytes(data, &cxReceipts); err != nil { |
||||
return nil, err |
||||
} |
||||
return cxReceipts, nil |
||||
} |
||||
|
||||
// WriteCXReceipts stores all the transaction receipts given destination shardID, blockNumber and blockHash
|
||||
func WriteCXReceipts(db DatabaseWriter, shardID uint32, number uint64, hash common.Hash, receipts types.CXReceipts) error { |
||||
bytes, err := rlp.EncodeToBytes(receipts) |
||||
if err != nil { |
||||
utils.Logger().Error().Msg("[WriteCXReceipts] Failed to encode cross shard tx receipts") |
||||
} |
||||
// Store the receipt slice
|
||||
if err := db.Put(cxReceiptKey(shardID, number, hash), bytes); err != nil { |
||||
utils.Logger().Error().Msg("[WriteCXReceipts] Failed to store cxreceipts") |
||||
} |
||||
return err |
||||
} |
||||
|
||||
// ReadCXReceiptsProofSpent check whether a CXReceiptsProof is unspent
|
||||
func ReadCXReceiptsProofSpent(db DatabaseReader, shardID uint32, number uint64) (byte, error) { |
||||
data, err := db.Get(cxReceiptSpentKey(shardID, number)) |
||||
if err != nil || len(data) == 0 { |
||||
return NAByte, ctxerror.New("[ReadCXReceiptsProofSpent] Cannot find the key", "shardID", shardID, "number", number).WithCause(err) |
||||
} |
||||
return data[0], nil |
||||
} |
||||
|
||||
// WriteCXReceiptsProofSpent write CXReceiptsProof as spent into database
|
||||
func WriteCXReceiptsProofSpent(dbw DatabaseWriter, cxp *types.CXReceiptsProof) error { |
||||
shardID := cxp.MerkleProof.ShardID |
||||
blockNum := cxp.MerkleProof.BlockNum.Uint64() |
||||
return dbw.Put(cxReceiptSpentKey(shardID, blockNum), []byte{SpentByte}) |
||||
} |
||||
|
||||
// DeleteCXReceiptsProofSpent removes unspent indicator of a given blockHash
|
||||
func DeleteCXReceiptsProofSpent(db DatabaseDeleter, shardID uint32, number uint64) { |
||||
if err := db.Delete(cxReceiptSpentKey(shardID, number)); err != nil { |
||||
utils.Logger().Error().Msg("Failed to delete receipts unspent indicator") |
||||
} |
||||
} |
||||
|
||||
// ReadValidatorSnapshot retrieves validator's snapshot by its address
|
||||
func ReadValidatorSnapshot( |
||||
db DatabaseReader, addr common.Address, epoch *big.Int, |
||||
) (*staking.ValidatorWrapper, error) { |
||||
data, err := db.Get(validatorSnapshotKey(addr, epoch)) |
||||
if err != nil || len(data) == 0 { |
||||
utils.Logger().Info().Err(err).Msg("ReadValidatorSnapshot") |
||||
return nil, err |
||||
} |
||||
v := staking.ValidatorWrapper{} |
||||
if err := rlp.DecodeBytes(data, &v); err != nil { |
||||
utils.Logger().Error().Err(err). |
||||
Str("address", addr.Hex()). |
||||
Msg("Unable to decode validator snapshot from database") |
||||
return nil, err |
||||
} |
||||
return &v, nil |
||||
} |
||||
|
||||
// WriteValidatorSnapshot stores validator's snapshot by its address
|
||||
func WriteValidatorSnapshot(batch DatabaseWriter, v *staking.ValidatorWrapper, epoch *big.Int) error { |
||||
bytes, err := rlp.EncodeToBytes(v) |
||||
if err != nil { |
||||
utils.Logger().Error().Msg("[WriteValidatorSnapshot] Failed to encode") |
||||
return err |
||||
} |
||||
if err := batch.Put(validatorSnapshotKey(v.Address, epoch), bytes); err != nil { |
||||
utils.Logger().Error().Msg("[WriteValidatorSnapshot] Failed to store to database") |
||||
return err |
||||
} |
||||
return err |
||||
} |
||||
|
||||
// DeleteValidatorSnapshot removes the validator's snapshot by its address
|
||||
func DeleteValidatorSnapshot(db DatabaseDeleter, addr common.Address, epoch *big.Int) { |
||||
if err := db.Delete(validatorSnapshotKey(addr, epoch)); err != nil { |
||||
utils.Logger().Error().Msg("Failed to delete snapshot of a validator") |
||||
} |
||||
} |
||||
|
||||
// ReadValidatorStats retrieves validator's stats by its address
|
||||
func ReadValidatorStats( |
||||
db DatabaseReader, addr common.Address, |
||||
) (*staking.ValidatorStats, error) { |
||||
data, err := db.Get(validatorStatsKey(addr)) |
||||
if err != nil || len(data) == 0 { |
||||
utils.Logger().Info().Err(err).Msg("ReadValidatorStats") |
||||
return nil, err |
||||
} |
||||
stats := staking.ValidatorStats{} |
||||
if err := rlp.DecodeBytes(data, &stats); err != nil { |
||||
utils.Logger().Error().Err(err). |
||||
Str("address", addr.Hex()). |
||||
Msg("Unable to decode validator stats from database") |
||||
return nil, err |
||||
} |
||||
return &stats, nil |
||||
} |
||||
|
||||
// WriteValidatorStats stores validator's stats by its address
|
||||
func WriteValidatorStats( |
||||
batch DatabaseWriter, addr common.Address, stats *staking.ValidatorStats, |
||||
) error { |
||||
bytes, err := rlp.EncodeToBytes(stats) |
||||
if err != nil { |
||||
utils.Logger().Error().Msg("[WriteValidatorStats] Failed to encode") |
||||
return err |
||||
} |
||||
if err := batch.Put(validatorStatsKey(addr), bytes); err != nil { |
||||
utils.Logger().Error().Msg("[WriteValidatorStats] Failed to store to database") |
||||
return err |
||||
} |
||||
return err |
||||
} |
||||
|
||||
// ReadValidatorList retrieves staking validator by its address
|
||||
// Return only active validators if activeOnly==true, otherwise, return all validators
|
||||
func ReadValidatorList(db DatabaseReader, activeOnly bool) ([]common.Address, error) { |
||||
key := validatorListKey |
||||
if activeOnly { |
||||
key = activeValidatorListKey |
||||
} |
||||
data, err := db.Get(key) |
||||
if err != nil || len(data) == 0 { |
||||
return []common.Address{}, nil |
||||
} |
||||
addrs := []common.Address{} |
||||
if err := rlp.DecodeBytes(data, &addrs); err != nil { |
||||
utils.Logger().Error().Err(err).Msg("Unable to Decode validator List from database") |
||||
return nil, err |
||||
} |
||||
return addrs, nil |
||||
} |
||||
|
||||
// WriteValidatorList stores staking validator's information by its address
|
||||
// Writes only for active validators if activeOnly==true, otherwise, writes for all validators
|
||||
func WriteValidatorList(db DatabaseWriter, addrs []common.Address, activeOnly bool) error { |
||||
key := validatorListKey |
||||
if activeOnly { |
||||
key = activeValidatorListKey |
||||
} |
||||
|
||||
bytes, err := rlp.EncodeToBytes(addrs) |
||||
if err != nil { |
||||
utils.Logger().Error().Msg("[WriteValidatorList] Failed to encode") |
||||
} |
||||
if err := db.Put(key, bytes); err != nil { |
||||
utils.Logger().Error().Msg("[WriteValidatorList] Failed to store to database") |
||||
} |
||||
return err |
||||
} |
||||
|
||||
// ReadDelegationsByDelegator retrieves the list of validators delegated by a delegator
|
||||
func ReadDelegationsByDelegator(db DatabaseReader, delegator common.Address) ([]staking.DelegationIndex, error) { |
||||
data, err := db.Get(delegatorValidatorListKey(delegator)) |
||||
if err != nil || len(data) == 0 { |
||||
return []staking.DelegationIndex{}, nil |
||||
} |
||||
addrs := []staking.DelegationIndex{} |
||||
if err := rlp.DecodeBytes(data, &addrs); err != nil { |
||||
utils.Logger().Error().Err(err).Msg("Unable to Decode delegations from database") |
||||
return nil, err |
||||
} |
||||
return addrs, nil |
||||
} |
||||
|
||||
// WriteDelegationsByDelegator stores the list of validators delegated by a delegator
|
||||
func WriteDelegationsByDelegator(db DatabaseWriter, delegator common.Address, indices []staking.DelegationIndex) error { |
||||
bytes, err := rlp.EncodeToBytes(indices) |
||||
if err != nil { |
||||
utils.Logger().Error().Msg("[writeDelegationsByDelegator] Failed to encode") |
||||
} |
||||
if err := db.Put(delegatorValidatorListKey(delegator), bytes); err != nil { |
||||
utils.Logger().Error().Msg("[writeDelegationsByDelegator] Failed to store to database") |
||||
} |
||||
return err |
||||
} |
||||
|
||||
// ReadBlockRewardAccumulator ..
|
||||
func ReadBlockRewardAccumulator(db DatabaseReader, number uint64) (*big.Int, error) { |
||||
data, err := db.Get(blockRewardAccumKey(number)) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return new(big.Int).SetBytes(data), nil |
||||
} |
||||
|
||||
// WriteBlockRewardAccumulator ..
|
||||
func WriteBlockRewardAccumulator(db DatabaseWriter, newAccum *big.Int, number uint64) error { |
||||
return db.Put(blockRewardAccumKey(number), newAccum.Bytes()) |
||||
} |
||||
|
||||
//// Resharding ////
|
||||
|
||||
// ReadEpochBlockNumber retrieves the epoch block number for the given epoch,
|
||||
// or nil if the given epoch is not found in the database.
|
||||
func ReadEpochBlockNumber(db DatabaseReader, epoch *big.Int) (*big.Int, error) { |
||||
data, err := db.Get(epochBlockNumberKey(epoch)) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return new(big.Int).SetBytes(data), nil |
||||
} |
||||
|
||||
// WriteEpochBlockNumber stores the given epoch-number-to-epoch-block-number in the database.
|
||||
func WriteEpochBlockNumber(db DatabaseWriter, epoch, blockNum *big.Int) error { |
||||
return db.Put(epochBlockNumberKey(epoch), blockNum.Bytes()) |
||||
} |
||||
|
||||
// ReadEpochVrfBlockNums retrieves the VRF block numbers for the given epoch
|
||||
func ReadEpochVrfBlockNums(db DatabaseReader, epoch *big.Int) ([]byte, error) { |
||||
return db.Get(epochVrfBlockNumbersKey(epoch)) |
||||
} |
||||
|
||||
// WriteEpochVrfBlockNums stores the VRF block numbers for the given epoch
|
||||
func WriteEpochVrfBlockNums(db DatabaseWriter, epoch *big.Int, data []byte) error { |
||||
return db.Put(epochVrfBlockNumbersKey(epoch), data) |
||||
} |
||||
|
||||
// ReadEpochVdfBlockNum retrieves the VDF block number for the given epoch
|
||||
func ReadEpochVdfBlockNum(db DatabaseReader, epoch *big.Int) ([]byte, error) { |
||||
return db.Get(epochVdfBlockNumberKey(epoch)) |
||||
} |
||||
|
||||
// WriteEpochVdfBlockNum stores the VDF block number for the given epoch
|
||||
func WriteEpochVdfBlockNum(db DatabaseWriter, epoch *big.Int, data []byte) error { |
||||
return db.Put(epochVdfBlockNumberKey(epoch), data) |
||||
} |
||||
|
||||
//// Resharding ////
|
Loading…
Reference in new issue