add staking transaction field in v2 body; add v3 header for future fork

pull/1721/head
chao 5 years ago
parent 96cb8d095a
commit 0c020d8f6a
  1. 3
      block/factory/factory.go
  2. 16
      block/v3/header.go
  3. 3
      consensus/engine/consensus_engine.go
  4. 10
      core/blockchain.go
  5. 2
      core/chain_makers.go
  6. 2
      core/genesis.go
  7. 6
      core/rawdb/accessors_chain.go
  8. 2
      core/state_processor.go
  9. 27
      core/types/block.go
  10. 128
      core/types/bodyv2.go
  11. 5
      internal/chain/engine.go
  12. 17
      internal/params/config.go
  13. 18
      node/node.go
  14. 4
      node/node_newblock.go
  15. 88
      node/worker/worker.go
  16. 28
      staking/types/transaction.go

@ -8,6 +8,7 @@ import (
v0 "github.com/harmony-one/harmony/block/v0"
v1 "github.com/harmony-one/harmony/block/v1"
v2 "github.com/harmony-one/harmony/block/v2"
v3 "github.com/harmony-one/harmony/block/v3"
"github.com/harmony-one/harmony/internal/params"
)
@ -29,6 +30,8 @@ func NewFactory(chainConfig *params.ChainConfig) Factory {
func (f *factory) NewHeader(epoch *big.Int) *block.Header {
var impl blockif.Header
switch {
case epoch.Cmp(f.chainConfig.StakingEpoch) >= 0:
impl = v3.NewHeader()
case epoch.Cmp(f.chainConfig.CrossLinkEpoch) >= 0:
impl = v2.NewHeader()
case epoch.Cmp(f.chainConfig.CrossTxEpoch) >= 0:

@ -0,0 +1,16 @@
package v3
import (
"github.com/harmony-one/harmony/block/v2"
)
// Header v3 has the same structure as v2 header
// It is used to identify the body v3 which including staking txs
type Header struct {
v2.Header
}
// NewHeader creates a new header object.
func NewHeader() *Header {
return &Header{*v2.NewHeader()}
}

@ -80,9 +80,8 @@ type Engine interface {
Finalize(
chain ChainReader, header *block.Header, state *state.DB,
txs []*types.Transaction,
stkgTxs []*staking.StakingTransaction,
receipts []*types.Receipt, outcxs []*types.CXReceipt,
incxs []*types.CXReceiptsProof) (*types.Block, error)
incxs []*types.CXReceiptsProof, stks []*staking.StakingTransaction) (*types.Block, error)
// Seal generates a new sealing request for the given input block and pushes
// the result into the given channel.

@ -2252,11 +2252,11 @@ func (bc *BlockChain) ReadTxLookupEntry(txID common.Hash) (common.Hash, uint64,
return rawdb.ReadTxLookupEntry(bc.db, txID)
}
// ReadStakingValidator reads staking information of given validator
func (bc *BlockChain) ReadStakingValidator(addr common.Address) (*staking.Validator, error) {
// ReadStakingValidator reads staking information of given validatorWrapper
func (bc *BlockChain) ReadStakingValidator(addr common.Address) (*staking.ValidatorWrapper, error) {
if cached, ok := bc.stakingCache.Get("staking-" + string(addr.Bytes())); ok {
by := cached.([]byte)
v := staking.Validator{}
v := staking.ValidatorWrapper{}
if err := rlp.DecodeBytes(by, &v); err != nil {
return nil, err
}
@ -2266,8 +2266,8 @@ func (bc *BlockChain) ReadStakingValidator(addr common.Address) (*staking.Valida
return rawdb.ReadStakingValidator(bc.db, addr)
}
// WriteStakingValidator reads staking information of given validator
func (bc *BlockChain) WriteStakingValidator(v *staking.Validator) error {
// WriteStakingValidator reads staking information of given validatorWrapper
func (bc *BlockChain) WriteStakingValidator(v *staking.ValidatorWrapper) error {
err := rawdb.WriteStakingValidator(bc.db, v)
if err != nil {
return err

@ -188,7 +188,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if b.engine != nil {
// Finalize and seal the block
block, err := b.engine.Finalize(chainreader, b.header, statedb, b.txs, b.stkTxs, b.receipts, nil, nil)
block, err := b.engine.Finalize(chainreader, b.header, statedb, b.txs, b.receipts, nil, nil, nil)
if err != nil {
panic(err)
}

@ -266,7 +266,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
statedb.Commit(false)
statedb.Database().TrieDB().Commit(root, true)
return types.NewBlock(head, nil, nil, nil, nil)
return types.NewBlock(head, nil, nil, nil, nil, nil)
}
// Commit writes the block and state of a genesis specification to the database.

@ -615,13 +615,13 @@ func WriteCXReceiptsProofUnspentCheckpoint(db DatabaseWriter, shardID uint32, bl
}
// ReadStakingValidator retrieves staking validator by its address
func ReadStakingValidator(db DatabaseReader, addr common.Address) (*staking.Validator, error) {
func ReadStakingValidator(db DatabaseReader, addr common.Address) (*staking.ValidatorWrapper, error) {
data, err := db.Get(stakingKey(addr))
if len(data) == 0 || err != nil {
utils.Logger().Info().Err(err).Msg("ReadStakingValidator")
return nil, err
}
v := staking.Validator{}
v := staking.ValidatorWrapper{}
if err := rlp.DecodeBytes(data, &v); err != nil {
utils.Logger().Error().Err(err).Str("address", addr.Hex()).Msg("Unable to Decode staking validator from database")
return nil, err
@ -630,7 +630,7 @@ func ReadStakingValidator(db DatabaseReader, addr common.Address) (*staking.Vali
}
// WriteStakingValidator stores staking validator's information by its address
func WriteStakingValidator(db DatabaseWriter, v *staking.Validator) error {
func WriteStakingValidator(db DatabaseWriter, v *staking.ValidatorWrapper) error {
bytes, err := rlp.EncodeToBytes(v)
if err != nil {
utils.Logger().Error().Msg("[WriteStakingValidator] Failed to encode")

@ -94,7 +94,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.DB, cfg vm.C
}
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
_, err := p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.StakingTransactions(), receipts, outcxs, incxs)
_, err := p.engine.Finalize(p.bc, header, statedb, block.Transactions(), receipts, outcxs, incxs, block.StakingTransactions())
if err != nil {
return nil, nil, nil, 0, ctxerror.New("cannot finalize block").WithCause(err)
}

@ -35,6 +35,7 @@ import (
v0 "github.com/harmony-one/harmony/block/v0"
v1 "github.com/harmony-one/harmony/block/v1"
v2 "github.com/harmony-one/harmony/block/v2"
v3 "github.com/harmony-one/harmony/block/v3"
"github.com/harmony-one/harmony/crypto/hash"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/shard"
@ -124,6 +125,8 @@ type Body struct {
func NewBodyForMatchingHeader(h *block.Header) (*Body, error) {
var bi BodyInterface
switch h.Header.(type) {
case *v3.Header:
bi = new(BodyV2)
case *v2.Header, *v1.Header:
bi = new(BodyV1)
case *v0.Header:
@ -186,6 +189,7 @@ type Block struct {
header *block.Header
uncles []*block.Header
transactions Transactions
stks staking.StakingTransactions
incomingReceipts CXReceiptsProofs
// caches
@ -239,11 +243,21 @@ type extblockV1 struct {
IncomingReceipts CXReceiptsProofs
}
// includes staking transaction
type extblockV2 struct {
Header *block.Header
Txs []*Transaction
Stks []*staking.StakingTransaction
Uncles []*block.Header
IncomingReceipts CXReceiptsProofs
}
var extblockReg = taggedrlp.NewRegistry()
func init() {
extblockReg.MustRegister(taggedrlp.LegacyTag, &extblock{})
extblockReg.MustRegister("v1", &extblockV1{})
extblockReg.MustRegister("v2", &extblockV2{})
}
// NewBlock creates a new block. The input data is copied,
@ -253,7 +267,7 @@ func init() {
// The values of TxHash, UncleHash, ReceiptHash and Bloom in header
// are ignored and set to values derived from the given txs,
// and receipts.
func NewBlock(header *block.Header, txs []*Transaction, receipts []*Receipt, outcxs []*CXReceipt, incxs []*CXReceiptsProof) *Block {
func NewBlock(header *block.Header, txs []*Transaction, receipts []*Receipt, outcxs []*CXReceipt, incxs []*CXReceiptsProof, stks []*staking.StakingTransaction) *Block {
b := &Block{header: CopyHeader(header)}
// TODO: panic if len(txs) != len(receipts)
@ -282,6 +296,11 @@ func NewBlock(header *block.Header, txs []*Transaction, receipts []*Receipt, out
copy(b.incomingReceipts, incxs)
}
if len(stks) > 0 {
b.stks = make(staking.StakingTransactions, len(stks))
copy(b.stks, stks)
}
return b
}
@ -308,6 +327,8 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
return err
}
switch eb := eb.(type) {
case *extblockV2:
b.header, b.uncles, b.transactions, b.incomingReceipts, b.stks = eb.Header, eb.Uncles, eb.Txs, eb.IncomingReceipts, eb.Stks
case *extblockV1:
b.header, b.uncles, b.transactions, b.incomingReceipts = eb.Header, eb.Uncles, eb.Txs, eb.IncomingReceipts
case *extblock:
@ -323,6 +344,8 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
func (b *Block) EncodeRLP(w io.Writer) error {
var eb interface{}
switch h := b.header.Header.(type) {
case *v3.Header:
eb = extblockV2{b.header, b.transactions, b.stks, b.uncles, b.incomingReceipts}
case *v2.Header, *v1.Header:
eb = extblockV1{b.header, b.transactions, b.uncles, b.incomingReceipts}
case *v0.Header:
@ -349,7 +372,7 @@ func (b *Block) Transactions() Transactions {
// StakingTransactions returns stakingTransactions.
func (b *Block) StakingTransactions() staking.StakingTransactions {
return staking.StakingTransactions{}
return b.stks
}
// IncomingReceipts returns verified outgoing receipts

@ -0,0 +1,128 @@
package types
import (
"io"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/block"
staking "github.com/harmony-one/harmony/staking/types"
)
// BodyV2 is the V2 block body
type BodyV2 struct {
f bodyFieldsV2
}
type bodyFieldsV2 struct {
Transactions []*Transaction
StakingTransactions []*staking.StakingTransaction
Uncles []*block.Header
IncomingReceipts CXReceiptsProofs
}
// Transactions returns the list of transactions.
//
// The returned list is a deep copy; the caller may do anything with it without
// affecting the original.
func (b *BodyV2) Transactions() (txs []*Transaction) {
for _, tx := range b.f.Transactions {
txs = append(txs, tx.Copy())
}
return txs
}
// StakingTransactions returns the list of staking transactions.
// The returned list is a deep copy; the caller may do anything with it without
// affecting the original.
func (b *BodyV2) StakingTransactions() (txs []*staking.StakingTransaction) {
for _, tx := range b.f.StakingTransactions {
txs = append(txs, tx.Copy())
}
return txs
}
// TransactionAt returns the transaction at the given index in this block.
// It returns nil if index is out of bounds.
func (b *BodyV2) TransactionAt(index int) *Transaction {
if index < 0 || index >= len(b.f.Transactions) {
return nil
}
return b.f.Transactions[index].Copy()
}
// CXReceiptAt returns the CXReceipt at given index in this block
// It returns nil if index is out of bounds
func (b *BodyV2) CXReceiptAt(index int) *CXReceipt {
if index < 0 {
return nil
}
for _, cxp := range b.f.IncomingReceipts {
cxs := cxp.Receipts
if index < len(cxs) {
return cxs[index].Copy()
}
index -= len(cxs)
}
return nil
}
// SetTransactions sets the list of transactions with a deep copy of the given
// list.
func (b *BodyV2) SetTransactions(newTransactions []*Transaction) {
var txs []*Transaction
for _, tx := range newTransactions {
txs = append(txs, tx.Copy())
}
b.f.Transactions = txs
}
// SetStakingTransactions sets the list of staking transactions with a deep copy of the given
// list.
func (b *BodyV2) SetStakingTransactions(newStakingTransactions []*staking.StakingTransaction) {
var txs []*staking.StakingTransaction
for _, tx := range newStakingTransactions {
txs = append(txs, tx.Copy())
}
b.f.StakingTransactions = txs
}
// Uncles returns a deep copy of the list of uncle headers of this block.
func (b *BodyV2) Uncles() (uncles []*block.Header) {
for _, uncle := range b.f.Uncles {
uncles = append(uncles, CopyHeader(uncle))
}
return uncles
}
// SetUncles sets the list of uncle headers with a deep copy of the given list.
func (b *BodyV2) SetUncles(newUncle []*block.Header) {
var uncles []*block.Header
for _, uncle := range newUncle {
uncles = append(uncles, CopyHeader(uncle))
}
b.f.Uncles = uncles
}
// IncomingReceipts returns a deep copy of the list of incoming cross-shard
// transaction receipts of this block.
func (b *BodyV2) IncomingReceipts() (incomingReceipts CXReceiptsProofs) {
return b.f.IncomingReceipts.Copy()
}
// SetIncomingReceipts sets the list of incoming cross-shard transaction
// receipts of this block with a dep copy of the given list.
func (b *BodyV2) SetIncomingReceipts(newIncomingReceipts CXReceiptsProofs) {
b.f.IncomingReceipts = newIncomingReceipts.Copy()
}
// EncodeRLP RLP-encodes the block body into the given writer.
func (b *BodyV2) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, &b.f)
}
// DecodeRLP RLP-decodes a block body from the given RLP stream into the
// receiver.
func (b *BodyV2) DecodeRLP(s *rlp.Stream) error {
return s.Decode(&b.f)
}

@ -151,16 +151,15 @@ func (e *engineImpl) VerifySeal(chain engine.ChainReader, header *block.Header)
// setting the final state and assembling the block.
func (e *engineImpl) Finalize(
chain engine.ChainReader, header *block.Header, state *state.DB, txs []*types.Transaction,
stkgTxs []*staking.StakingTransaction,
receipts []*types.Receipt, outcxs []*types.CXReceipt,
incxs []*types.CXReceiptsProof) (*types.Block, error) {
incxs []*types.CXReceiptsProof, stks []*staking.StakingTransaction) (*types.Block, error) {
// Accumulate any block and uncle rewards and commit the final state root
// Header seems complete, assemble into a block and return
if err := AccumulateRewards(chain, state, header); err != nil {
return nil, ctxerror.New("cannot pay block reward").WithCause(err)
}
header.SetRoot(state.IntermediateRoot(chain.Config().IsS3(header.Epoch())))
return types.NewBlock(header, txs, receipts, outcxs, incxs), nil
return types.NewBlock(header, txs, receipts, outcxs, incxs, stks), nil
}
// QuorumForBlock returns the quorum for the given block header.

@ -26,6 +26,7 @@ var (
ChainID: MainnetChainID,
CrossTxEpoch: big.NewInt(28),
CrossLinkEpoch: EpochTBD,
StakingEpoch: EpochTBD,
EIP155Epoch: big.NewInt(28),
S3Epoch: big.NewInt(28),
}
@ -35,6 +36,7 @@ var (
ChainID: TestnetChainID,
CrossTxEpoch: big.NewInt(1),
CrossLinkEpoch: big.NewInt(2),
StakingEpoch: big.NewInt(3),
EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0),
}
@ -45,6 +47,7 @@ var (
ChainID: PangaeaChainID,
CrossTxEpoch: big.NewInt(0),
CrossLinkEpoch: EpochTBD,
StakingEpoch: EpochTBD,
EIP155Epoch: big.NewInt(0),
S3Epoch: big.NewInt(0),
}
@ -56,6 +59,7 @@ var (
AllProtocolChangesChainID, // ChainID
big.NewInt(0), // CrossTxEpoch
big.NewInt(0), // CrossLinkEpoch
big.NewInt(0), // StakingEpoch
big.NewInt(0), // EIP155Epoch
big.NewInt(0), // S3Epoch
}
@ -67,6 +71,7 @@ var (
TestChainID, // ChainID
big.NewInt(0), // CrossTxEpoch
big.NewInt(0), // CrossLinkEpoch
big.NewInt(0), // StakingEpoch
big.NewInt(0), // EIP155Epoch
big.NewInt(0), // S3Epoch
}
@ -103,16 +108,20 @@ type ChainConfig struct {
// cross-shard links.
CrossLinkEpoch *big.Int `json:"crossLinkEpoch,omitempty"`
// StakingEpoch is the epoch we allow staking transactions
StakingEpoch *big.Int `json:"stakingEpoch,omitempty"`
EIP155Epoch *big.Int `json:"eip155Epoch,omitempty"` // EIP155 hard fork epoch (include EIP158 too)
S3Epoch *big.Int `json:"s3Epoch,omitempty"` // S3 epoch is the first epoch containing S3 mainnet and all ethereum update up to Constantinople
}
// String implements the fmt.Stringer interface.
func (c *ChainConfig) String() string {
return fmt.Sprintf("{ChainID: %v EIP155: %v CrossTx: %v CrossLink: %v}",
return fmt.Sprintf("{ChainID: %v EIP155: %v CrossTx: %v Staking: %v CrossLink: %v}",
c.ChainID,
c.EIP155Epoch,
c.CrossTxEpoch,
c.StakingEpoch,
c.CrossLinkEpoch,
)
}
@ -137,6 +146,12 @@ func (c *ChainConfig) IsCrossTx(epoch *big.Int) bool {
return isForked(crossTxEpoch, epoch)
}
// IsStaking determines whether it is staking epoch
func (c *ChainConfig) IsStaking(epoch *big.Int) bool {
stkEpoch := new(big.Int).Add(c.StakingEpoch, common.Big1)
return isForked(stkEpoch, epoch)
}
// IsCrossLink returns whether epoch is either equal to the CrossLink fork epoch or greater.
func (c *ChainConfig) IsCrossLink(epoch *big.Int) bool {
return isForked(c.CrossLinkEpoch, epoch)

@ -347,7 +347,7 @@ func (node *Node) AddPendingReceipts(receipts *types.CXReceiptsProof) {
// Note the pending transaction list will then contain the rest of the txs
func (node *Node) getTransactionsForNewBlock(
coinbase common.Address,
) (types.Transactions, staking.StakingTransactions) {
) types.Transactions {
txsThrottleConfig := core.ShardingSchedule.TxsThrottleConfig()
@ -368,7 +368,7 @@ func (node *Node) getTransactionsForNewBlock(
utils.Logger().Error().
Err(err).
Msg("Failed updating worker's state before txn selection")
return types.Transactions{}, staking.StakingTransactions{}
return types.Transactions{}
}
node.pendingTxMutex.Lock()
@ -387,8 +387,6 @@ func (node *Node) getTransactionsForNewBlock(
}
selected, unselected, invalid := node.Worker.SelectTransactionsForNewBlock(newBlockNum, pendingTransactions, node.recentTxsStats, txsThrottleConfig, coinbase)
selectedStaking, unselectedStaking, invalidStaking :=
node.Worker.SelectStakingTransactionsForNewBlock(newBlockNum, pendingStakingTransactions, coinbase)
node.pendingTransactions = make(map[common.Hash]*types.Transaction)
for _, unselectedTx := range unselected {
@ -400,17 +398,7 @@ func (node *Node) getTransactionsForNewBlock(
Int("invalidDiscarded", len(invalid)).
Msg("Selecting Transactions")
node.pendingStakingTransactions = make(map[common.Hash]*staking.StakingTransaction)
for _, unselectedStakingTx := range unselectedStaking {
node.pendingStakingTransactions[unselectedStakingTx.Hash()] = unselectedStakingTx
}
utils.Logger().Info().
Int("remainPending", len(node.pendingStakingTransactions)).
Int("selected", len(unselectedStaking)).
Int("invalidDiscarded", len(invalidStaking)).
Msg("Selecting Transactions")
return selected, selectedStaking
return selected
}
func (node *Node) startRxPipeline(

@ -81,9 +81,9 @@ func (node *Node) proposeNewBlock() (*types.Block, error) {
coinbase := node.Consensus.SelfAddress
// Prepare transactions including staking transactions
selectedTxs, selectedStakingTxs := node.getTransactionsForNewBlock(coinbase)
selectedTxs := node.getTransactionsForNewBlock(coinbase)
if err := node.Worker.CommitTransactions(selectedTxs, selectedStakingTxs, coinbase); err != nil {
if err := node.Worker.CommitTransactions(selectedTxs, coinbase); err != nil {
ctxerror.Log15(utils.GetLogger().Error,
ctxerror.New("cannot commit transactions").
WithCause(err))

@ -13,7 +13,6 @@ import (
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/core/vm"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
"github.com/harmony-one/harmony/internal/ctxerror"
@ -145,63 +144,6 @@ func (w *Worker) SelectTransactionsForNewBlock(newBlockNum uint64, txs types.Tra
return selected, unselected, invalid
}
// SelectStakingTransactionsForNewBlock selects staking transactions for new block.
func (w *Worker) SelectStakingTransactionsForNewBlock(
newBlockNum uint64, txs staking.StakingTransactions,
coinbase common.Address) (staking.StakingTransactions, staking.StakingTransactions, staking.StakingTransactions) {
// only beaconchain process staking transaction
if w.chain.ShardID() != values.BeaconChainShardID {
return nil, nil, nil
}
// staking transaction share the same gasPool with normal transactions
if w.current.gasPool == nil {
w.current.gasPool = new(core.GasPool).AddGas(w.current.header.GasLimit())
}
selected := staking.StakingTransactions{}
unselected := staking.StakingTransactions{}
invalid := staking.StakingTransactions{}
for _, tx := range txs {
snap := w.current.state.Snapshot()
_, err := w.commitStakingTransaction(tx, coinbase)
if err != nil {
w.current.state.RevertToSnapshot(snap)
invalid = append(invalid, tx)
utils.Logger().Error().Err(err).Str("stakingTxId", tx.Hash().Hex()).Msg("Commit staking transaction error")
} else {
selected = append(selected, tx)
utils.Logger().Info().Str("stakingTxId", tx.Hash().Hex()).Uint64("txGasLimit", tx.Gas()).Msg("StakingTransaction gas limit info")
}
}
utils.Logger().Info().Uint64("newBlockNum", newBlockNum).Uint64("blockGasLimit",
w.current.header.GasLimit()).Uint64("blockGasUsed",
w.current.header.GasUsed()).Msg("[SelectStakingTransaction] Block gas limit and usage info")
return selected, unselected, invalid
}
func (w *Worker) commitStakingTransaction(tx *staking.StakingTransaction, coinbase common.Address) ([]*types.Log, error) {
snap := w.current.state.Snapshot()
gasUsed := w.current.header.GasUsed()
receipt, _, err :=
core.ApplyStakingTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &gasUsed, vm.Config{})
w.current.header.SetGasUsed(gasUsed)
if err != nil {
w.current.state.RevertToSnapshot(snap)
return nil, err
}
if receipt == nil {
return nil, fmt.Errorf("nil staking receipt")
}
w.current.stkingTxs = append(w.current.stkingTxs, tx)
w.current.receipts = append(w.current.receipts, receipt)
return receipt.Logs, nil
}
func (w *Worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) {
snap := w.current.state.Snapshot()
@ -227,7 +169,7 @@ func (w *Worker) commitTransaction(tx *types.Transaction, coinbase common.Addres
// CommitTransactions commits transactions including staking transactions.
func (w *Worker) CommitTransactions(
txs types.Transactions, stakingTxns staking.StakingTransactions, coinbase common.Address) error {
txs types.Transactions, coinbase common.Address) error {
// Must update to the correct current state before processing potential txns
if err := w.UpdateCurrent(coinbase); err != nil {
utils.Logger().Error().
@ -248,10 +190,6 @@ func (w *Worker) CommitTransactions(
}
}
for _, stakingTx := range stakingTxns {
_ = stakingTx
// TODO: add logic to commit staking txns
}
return nil
}
@ -393,11 +331,14 @@ func (w *Worker) FinalizeNewBlock(sig []byte, signers []byte, viewID uint64, coi
}
}
stks, _, err := w.UpdateStakeInformation()
s := w.current.state.Copy()
copyHeader := types.CopyHeader(w.current.header)
block, err := w.engine.Finalize(
w.chain, copyHeader, s, w.current.txs, w.current.stkingTxs, w.current.receipts, w.current.outcxs, w.current.incxs,
w.chain, copyHeader, s, w.current.txs, w.current.receipts, w.current.outcxs, w.current.incxs,
stks,
)
if err != nil {
return nil, ctxerror.New("cannot finalize block").WithCause(err)
@ -405,6 +346,25 @@ func (w *Worker) FinalizeNewBlock(sig []byte, signers []byte, viewID uint64, coi
return block, nil
}
// UpdateStakeInformation updates validator and its delegation information
func (w *Worker) UpdateStakeInformation() ([]*staking.StakingTransaction, []*staking.ValidatorWrapper, error) {
// node.pendingStakingTransactions = make(map[common.Hash]*staking.StakingTransaction)
// for _, unselectedStakingTx := range unselectedStaking {
// node.pendingStakingTransactions[unselectedStakingTx.Hash()] = unselectedStakingTx
// }
addrs, err := w.chain.ReadValidatorList()
if err != nil {
return nil, nil, err
}
//validatorInfo := []staking.ValidatorWrapper{}
for _, addr := range addrs {
_ = addr
}
return nil, nil, nil
}
// New create a new worker object.
func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus_engine.Engine) *Worker {
worker := &Worker{

@ -4,6 +4,7 @@ import (
"errors"
"io"
"math/big"
"reflect"
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
@ -25,6 +26,26 @@ type txdata struct {
Hash *common.Hash `json:"hash" rlp:"-"`
}
func (d *txdata) CopyFrom(d2 *txdata) {
d.Directive = d2.Directive
d.AccountNonce = d2.AccountNonce
d.Price = new(big.Int).Set(d2.Price)
d.GasLimit = d2.GasLimit
d.StakeMsg = reflect.New(reflect.ValueOf(d2.StakeMsg).Elem().Type()).Interface()
d.V = new(big.Int).Set(d2.V)
d.R = new(big.Int).Set(d2.R)
d.S = new(big.Int).Set(d2.S)
d.Hash = copyHash(d2.Hash)
}
func copyHash(hash *common.Hash) *common.Hash {
if hash == nil {
return nil
}
copy := *hash
return &copy
}
// StakingTransaction is a record captuing all staking operations
type StakingTransaction struct {
data txdata
@ -76,6 +97,13 @@ func (tx *StakingTransaction) Hash() common.Hash {
return v
}
// Copy returns a copy of the transaction.
func (tx *StakingTransaction) Copy() *StakingTransaction {
var tx2 StakingTransaction
tx2.data.CopyFrom(&tx.data)
return &tx2
}
// WithSignature returns a new transaction with the given signature.
func (tx *StakingTransaction) WithSignature(signer Signer, sig []byte) (*StakingTransaction, error) {
r, s, v, err := signer.SignatureValues(tx, sig)

Loading…
Cancel
Save