Further progress on staking (#1709)

* [staking] Factor some project errors into values core/pkg. Thread stking Txs through Finalize

* [staking] Incorporate Chao code from PR 1700

* [staking] Remove dead staking code, create const values, factor out dec from staking

* [staking] Remove voting power for now till discussion, factor out more error values
pull/1713/head
Edgar Aroutiounian 5 years ago committed by GitHub
parent 3b52046a39
commit 97efce2766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      cmd/client/txgen/main.go
  2. 44
      cmd/staking/root.go
  3. 27
      consensus/README.md
  4. 113
      consensus/consensus.go
  5. 12
      consensus/engine/consensus_engine.go
  6. 35
      contracts/structs/structs.go
  7. 6
      core/block_validator.go
  8. 16
      core/blockchain.go
  9. 10
      core/chain_makers.go
  10. 4
      core/gaspool.go
  11. 2
      core/numeric/decimal.go
  12. 2
      core/numeric/decimal_test.go
  13. 39
      core/resharding.go
  14. 16
      core/state_processor.go
  15. 8
      core/state_transition.go
  16. 65
      core/tx_pool.go
  17. 22
      core/tx_pool_test.go
  18. 16
      core/types/block.go
  19. 10
      core/values/blockchain.go
  20. 38
      core/values/error.go
  21. 12
      internal/chain/engine.go
  22. 2
      internal/chain/reward.go
  23. 6
      internal/hmyapi/transactionpool.go
  24. 21
      node/node.go
  25. 3
      node/node_newblock.go
  26. 10
      node/node_resharding.go
  27. 62
      node/worker/worker.go
  28. 5
      shard/shard_state.go
  29. 14
      staking/types/commission.go
  30. 5
      staking/types/messages.go
  31. 4
      staking/types/sign.go
  32. 5
      staking/types/transaction.go
  33. 24
      staking/types/validator.go

@ -88,7 +88,6 @@ func setUpTXGen() *node.Node {
shardID := *shardIDFlag shardID := *shardIDFlag
selfPeer := p2p.Peer{IP: *ip, Port: *port, ConsensusPubKey: peerPubKey} selfPeer := p2p.Peer{IP: *ip, Port: *port, ConsensusPubKey: peerPubKey}
gsif, err := consensus.NewGenesisStakeInfoFinder()
// Nodes containing blockchain data to mirror the shards' data in the network // Nodes containing blockchain data to mirror the shards' data in the network
myhost, err := p2pimpl.NewHost(&selfPeer, nodePriKey) myhost, err := p2pimpl.NewHost(&selfPeer, nodePriKey)
@ -103,7 +102,6 @@ func setUpTXGen() *node.Node {
chainDBFactory := &shardchain.MemDBFactory{} chainDBFactory := &shardchain.MemDBFactory{}
txGen := node.New(myhost, consensusObj, chainDBFactory, false) //Changed it : no longer archival node. txGen := node.New(myhost, consensusObj, chainDBFactory, false) //Changed it : no longer archival node.
txGen.Client = client.NewClient(txGen.GetHost(), uint32(shardID)) txGen.Client = client.NewClient(txGen.GetHost(), uint32(shardID))
consensusObj.SetStakeInfoFinder(gsif)
consensusObj.ChainReader = txGen.Blockchain() consensusObj.ChainReader = txGen.Blockchain()
consensusObj.PublicKeys = nil consensusObj.PublicKeys = nil
genesisShardingConfig := core.ShardingSchedule.InstanceForEpoch(big.NewInt(core.GenesisEpoch)) genesisShardingConfig := core.ShardingSchedule.InstanceForEpoch(big.NewInt(core.GenesisEpoch))

@ -57,29 +57,29 @@ func (s *staker) run(cmd *cobra.Command, args []string) error {
p.DeserializeHexStr(testBLSPubKey) p.DeserializeHexStr(testBLSPubKey)
pub := shard.BlsPublicKey{} pub := shard.BlsPublicKey{}
pub.FromLibBLSPublicKey(p) pub.FromLibBLSPublicKey(p)
return staking.DirectiveNewValidator, staking.NewValidator{ // return staking.DirectiveNewValidator, staking.NewValidator{
Description: staking.Description{ // Description: staking.Description{
Name: "something", // Name: "something",
Identity: "something else", // Identity: "something else",
Website: "some site, harmony.one", // Website: "some site, harmony.one",
SecurityContact: "mr.smith", // SecurityContact: "mr.smith",
Details: "blah blah details", // Details: "blah blah details",
}, // },
CommissionRates: staking.CommissionRates{ // CommissionRates: staking.CommissionRates{
Rate: staking.NewDec(100), // Rate: staking.NewDec(100),
MaxRate: staking.NewDec(150), // MaxRate: staking.NewDec(150),
MaxChangeRate: staking.NewDec(5), // MaxChangeRate: staking.NewDec(5),
}, // },
MinSelfDelegation: big.NewInt(10), // MinSelfDelegation: big.NewInt(10),
StakingAddress: common.Address(dAddr), // StakingAddress: common.Address(dAddr),
PubKey: pub, // PubKey: pub,
Amount: big.NewInt(100), // Amount: big.NewInt(100),
}
// return message.DirectiveDelegate, message.Delegate{
// common.Address(dAddr),
// common.Address(dAddr),
// big.NewInt(10),
// } // }
return staking.DirectiveDelegate, staking.Delegate{
common.Address(dAddr),
common.Address(dAddr),
big.NewInt(10),
}
} }
stakingTx, err := staking.NewStakingTransaction(2, 100, gasPrice, stakePayloadMaker) stakingTx, err := staking.NewStakingTransaction(2, 100, gasPrice, stakePayloadMaker)

@ -1,8 +1,13 @@
Consensus package includes the Harmony BFT consensus protocol code, which uses BLS-based multi-signature to cosign the new block. The details are in Harmony's new [consensus protocol design](https://talk.harmony.one/t/bls-based-practical-bft-consensus/131). Consensus package includes the Harmony BFT consensus protocol code, which uses BLS-based
multi-signature to cosign the new block. The details are
in Harmony's new [consensus protocol design](https://talk.harmony.one/t/bls-based-practical-bft-consensus/131).
## Introduction to Harmony BFT with BLS signatures ## Introduction to Harmony BFT with BLS signatures
Harmony BFT consensus protocol consist of normal mode and view changing mode which is same as the PBFT(practical byzantine fault tolerance) protocol. The difference is we use the BLS aggregated signature to reduce O(N^2) communications to O(N), which is more efficient and scalable to traditional PBFT. For brevity, we will still call the whole process as PBFT. Harmony BFT consensus protocol consist of normal mode and view changing mode which is same
as the PBFT(practical byzantine fault tolerance) protocol. The difference is we use the
BLS aggregated signature to reduce O(N^2) communications to O(N), which is more efficient
and scalable to traditional PBFT. For brevity, we will still call the whole process as PBFT.
### Normal mode ### Normal mode
@ -81,21 +86,3 @@ func (consensus *Consensus) Start(stopChan chan struct{}, stoppedChan chan struc
``` ```

@ -8,19 +8,13 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/contracts/structs"
"github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
bls_cosi "github.com/harmony-one/harmony/crypto/bls" bls_cosi "github.com/harmony-one/harmony/crypto/bls"
"github.com/harmony-one/harmony/internal/ctxerror"
"github.com/harmony-one/harmony/internal/genesis"
"github.com/harmony-one/harmony/internal/memprofiling" "github.com/harmony-one/harmony/internal/memprofiling"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/shard"
) )
const ( const (
@ -150,9 +144,6 @@ type Consensus struct {
// MessageSender takes are of sending consensus message and the corresponding retry logic. // MessageSender takes are of sending consensus message and the corresponding retry logic.
msgSender *MessageSender msgSender *MessageSender
// Staking information finder
stakeInfoFinder StakeInfoFinder
// Used to convey to the consensus main loop that block syncing has finished. // Used to convey to the consensus main loop that block syncing has finished.
syncReadyChan chan struct{} syncReadyChan chan struct{}
// Used to convey to the consensus main loop that node is out of sync // Used to convey to the consensus main loop that node is out of sync
@ -171,18 +162,6 @@ func (consensus *Consensus) SetCommitDelay(delay time.Duration) {
consensus.delayCommit = delay consensus.delayCommit = delay
} }
// StakeInfoFinder returns the stake information finder instance this
// consensus uses, e.g. for block reward distribution.
func (consensus *Consensus) StakeInfoFinder() StakeInfoFinder {
return consensus.stakeInfoFinder
}
// SetStakeInfoFinder sets the stake information finder instance this
// consensus uses, e.g. for block reward distribution.
func (consensus *Consensus) SetStakeInfoFinder(stakeInfoFinder StakeInfoFinder) {
consensus.stakeInfoFinder = stakeInfoFinder
}
// DisableViewChangeForTestingOnly makes the receiver not propose view // DisableViewChangeForTestingOnly makes the receiver not propose view
// changes when it should, e.g. leader timeout. // changes when it should, e.g. leader timeout.
// //
@ -235,19 +214,6 @@ func (consensus *Consensus) GetBlockReward() *big.Int {
return consensus.lastBlockReward return consensus.lastBlockReward
} }
// StakeInfoFinder finds the staking account for the given consensus key.
type StakeInfoFinder interface {
// FindStakeInfoByNodeKey returns a list of staking information matching
// the given node key. Caller may modify the returned slice of StakeInfo
// struct pointers, but must not modify the StakeInfo structs themselves.
FindStakeInfoByNodeKey(key *bls.PublicKey) []*structs.StakeInfo
// FindStakeInfoByAccount returns a list of staking information matching
// the given account. Caller may modify the returned slice of StakeInfo
// struct pointers, but must not modify the StakeInfo structs themselves.
FindStakeInfoByAccount(addr common.Address) []*structs.StakeInfo
}
// New creates a new Consensus object // New creates a new Consensus object
// TODO: put shardId into chain reader's chain config // TODO: put shardId into chain reader's chain config
func New(host p2p.Host, ShardID uint32, leader p2p.Peer, blsPriKey *bls.SecretKey) (*Consensus, error) { func New(host p2p.Host, ShardID uint32, leader p2p.Peer, blsPriKey *bls.SecretKey) (*Consensus, error) {
@ -255,19 +221,15 @@ func New(host p2p.Host, ShardID uint32, leader p2p.Peer, blsPriKey *bls.SecretKe
consensus.host = host consensus.host = host
consensus.msgSender = NewMessageSender(host) consensus.msgSender = NewMessageSender(host)
consensus.blockNumLowChan = make(chan struct{}) consensus.blockNumLowChan = make(chan struct{})
// pbft related // pbft related
consensus.PbftLog = NewPbftLog() consensus.PbftLog = NewPbftLog()
consensus.phase = Announce consensus.phase = Announce
consensus.mode = PbftMode{mode: Normal} consensus.mode = PbftMode{mode: Normal}
// pbft timeout // pbft timeout
consensus.consensusTimeout = createTimeout() consensus.consensusTimeout = createTimeout()
consensus.prepareSigs = map[string]*bls.Sign{} consensus.prepareSigs = map[string]*bls.Sign{}
consensus.commitSigs = map[string]*bls.Sign{} consensus.commitSigs = map[string]*bls.Sign{}
consensus.CommitteePublicKeys = make(map[string]bool) consensus.CommitteePublicKeys = make(map[string]bool)
consensus.validators.Store(leader.ConsensusPubKey.SerializeToHexStr(), leader) consensus.validators.Store(leader.ConsensusPubKey.SerializeToHexStr(), leader)
if blsPriKey != nil { if blsPriKey != nil {
@ -283,90 +245,15 @@ func New(host p2p.Host, ShardID uint32, leader p2p.Peer, blsPriKey *bls.SecretKe
// as it was displayed on explorer as Height right now // as it was displayed on explorer as Height right now
consensus.viewID = 0 consensus.viewID = 0
consensus.ShardID = ShardID consensus.ShardID = ShardID
consensus.MsgChan = make(chan []byte) consensus.MsgChan = make(chan []byte)
consensus.syncReadyChan = make(chan struct{}) consensus.syncReadyChan = make(chan struct{})
consensus.syncNotReadyChan = make(chan struct{}) consensus.syncNotReadyChan = make(chan struct{})
consensus.commitFinishChan = make(chan uint64) consensus.commitFinishChan = make(chan uint64)
consensus.ReadySignal = make(chan struct{}) consensus.ReadySignal = make(chan struct{})
consensus.lastBlockReward = big.NewInt(0) consensus.lastBlockReward = big.NewInt(0)
// channel for receiving newly generated VDF // channel for receiving newly generated VDF
consensus.RndChannel = make(chan [vdfAndSeedSize]byte) consensus.RndChannel = make(chan [vdfAndSeedSize]byte)
consensus.uniqueIDInstance = utils.GetUniqueValidatorIDInstance() consensus.uniqueIDInstance = utils.GetUniqueValidatorIDInstance()
memprofiling.GetMemProfiling().Add("consensus.pbftLog", consensus.PbftLog) memprofiling.GetMemProfiling().Add("consensus.pbftLog", consensus.PbftLog)
return &consensus, nil return &consensus, nil
} }
// GenesisStakeInfoFinder is a stake info finder implementation using only
// genesis accounts.
// When used for block reward, it rewards only foundational nodes.
type GenesisStakeInfoFinder struct {
byNodeKey map[shard.BlsPublicKey][]*structs.StakeInfo
byAccount map[common.Address][]*structs.StakeInfo
}
// FindStakeInfoByNodeKey returns the genesis account matching the given node
// key, as a single-item StakeInfo list.
// It returns nil if the key is not a genesis node key.
func (f *GenesisStakeInfoFinder) FindStakeInfoByNodeKey(
key *bls.PublicKey,
) []*structs.StakeInfo {
var pk shard.BlsPublicKey
if err := pk.FromLibBLSPublicKey(key); err != nil {
utils.Logger().Warn().Err(err).Msg("cannot convert BLS public key")
return nil
}
l, _ := f.byNodeKey[pk]
return l
}
// FindStakeInfoByAccount returns the genesis account matching the given
// address, as a single-item StakeInfo list.
// It returns nil if the address is not a genesis account.
func (f *GenesisStakeInfoFinder) FindStakeInfoByAccount(
addr common.Address,
) []*structs.StakeInfo {
l, _ := f.byAccount[addr]
return l
}
// NewGenesisStakeInfoFinder returns a stake info finder that can look up
// genesis nodes.
func NewGenesisStakeInfoFinder() (*GenesisStakeInfoFinder, error) {
f := &GenesisStakeInfoFinder{
byNodeKey: make(map[shard.BlsPublicKey][]*structs.StakeInfo),
byAccount: make(map[common.Address][]*structs.StakeInfo),
}
for idx, account := range genesis.HarmonyAccounts {
pub := &bls.PublicKey{}
pub.DeserializeHexStr(account.BlsPublicKey)
var blsPublicKey shard.BlsPublicKey
if err := blsPublicKey.FromLibBLSPublicKey(pub); err != nil {
return nil, ctxerror.New("cannot convert BLS public key",
"accountIndex", idx,
).WithCause(err)
}
addressBytes, err := hexutil.Decode(account.Address)
if err != nil {
return nil, ctxerror.New("cannot decode account address",
"accountIndex", idx,
).WithCause(err)
}
var address common.Address
address.SetBytes(addressBytes)
stakeInfo := &structs.StakeInfo{
Account: address,
BlsPublicKey: blsPublicKey,
BlockNum: common.Big0,
LockPeriodCount: big.NewInt(0x7fffffffffffffff),
Amount: common.Big0,
}
f.byNodeKey[blsPublicKey] = append(f.byNodeKey[blsPublicKey], stakeInfo)
f.byAccount[address] = append(f.byAccount[address], stakeInfo)
}
return f, nil
}

@ -4,12 +4,12 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
) )
// ChainReader defines a small collection of methods needed to access the local // ChainReader defines a small collection of methods needed to access the local
@ -77,8 +77,12 @@ type Engine interface {
// and assembles the final block. // and assembles the final block.
// Note: The block header and state database might be updated to reflect any // Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards). // consensus rules that happen at finalization (e.g. block rewards).
Finalize(chain ChainReader, header *block.Header, state *state.DB, txs []*types.Transaction, Finalize(
receipts []*types.Receipt, outcxs []*types.CXReceipt, incxs []*types.CXReceiptsProof) (*types.Block, error) 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)
// Seal generates a new sealing request for the given input block and pushes // Seal generates a new sealing request for the given input block and pushes
// the result into the given channel. // the result into the given channel.

@ -1,35 +0,0 @@
package structs
import (
"math/big"
"github.com/harmony-one/harmony/shard"
"github.com/ethereum/go-ethereum/common"
)
// StakeInfoReturnValue is the struct for the return value of listLockedAddresses func in stake contract.
type StakeInfoReturnValue struct {
LockedAddresses []common.Address
BlsPubicKeys1 [][32]byte
BlsPubicKeys2 [][32]byte
BlsPubicKeys3 [][32]byte // TODO: remove third part as know we use 48 bytes pub key
BlockNums []*big.Int
LockPeriodCounts []*big.Int // The number of locking period the token will be locked.
Amounts []*big.Int
}
// StakeInfo stores the staking information for a staker.
type StakeInfo struct {
Account common.Address
BlsPublicKey shard.BlsPublicKey
BlockNum *big.Int
LockPeriodCount *big.Int // The number of locking period the token will be locked.
Amount *big.Int
}
// PlayersInfo stores the result of getPlayers.
type PlayersInfo struct {
Players []common.Address
Balances []*big.Int
}

@ -24,11 +24,11 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/internal/ctxerror"
consensus_engine "github.com/harmony-one/harmony/consensus/engine" consensus_engine "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/internal/ctxerror"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
) )
@ -58,7 +58,7 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin
func (v *BlockValidator) ValidateBody(block *types.Block) error { func (v *BlockValidator) ValidateBody(block *types.Block) error {
// Check whether the block's known, and if not, that it's linkable // Check whether the block's known, and if not, that it's linkable
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) { if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
return ErrKnownBlock return values.ErrKnownBlock
} }
if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {

@ -35,19 +35,18 @@ import (
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/harmony-one/harmony/internal/params"
lru "github.com/hashicorp/golang-lru"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
consensus_engine "github.com/harmony-one/harmony/consensus/engine" consensus_engine "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/contracts/structs"
"github.com/harmony-one/harmony/core/rawdb" "github.com/harmony-one/harmony/core/rawdb"
"github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
lru "github.com/hashicorp/golang-lru"
) )
var ( var (
@ -1250,7 +1249,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
err = bc.Validator().ValidateBody(block) err = bc.Validator().ValidateBody(block)
} }
switch { switch {
case err == ErrKnownBlock: case err == values.ErrKnownBlock:
// Block and state both already known. However if the current block is below // Block and state both already known. However if the current block is below
// this number we did a rollback and we should reimport it nonetheless. // this number we did a rollback and we should reimport it nonetheless.
if bc.CurrentBlock().NumberU64() >= block.NumberU64() { if bc.CurrentBlock().NumberU64() >= block.NumberU64() {
@ -1909,15 +1908,12 @@ func (bc *BlockChain) GetVrfByNumber(number uint64) []byte {
// GetShardState returns the shard state for the given epoch, // GetShardState returns the shard state for the given epoch,
// creating one if needed. // creating one if needed.
func (bc *BlockChain) GetShardState( func (bc *BlockChain) GetShardState(epoch *big.Int) (shard.State, error) {
epoch *big.Int,
stakeInfo *map[common.Address]*structs.StakeInfo,
) (shard.State, error) {
shardState, err := bc.ReadShardState(epoch) shardState, err := bc.ReadShardState(epoch)
if err == nil { // TODO ek – distinguish ErrNotFound if err == nil { // TODO ek – distinguish ErrNotFound
return shardState, err return shardState, err
} }
shardState, err = CalculateNewShardState(bc, epoch, stakeInfo) shardState, err = CalculateNewShardState(bc, epoch)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -23,15 +23,15 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
blockfactory "github.com/harmony-one/harmony/block/factory"
consensus_engine "github.com/harmony-one/harmony/consensus/engine" consensus_engine "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
) )
// BlockGen creates blocks for testing. // BlockGen creates blocks for testing.
@ -46,6 +46,7 @@ type BlockGen struct {
gasPool *GasPool gasPool *GasPool
txs []*types.Transaction txs []*types.Transaction
stkTxs staking.StakingTransactions
receipts []*types.Receipt receipts []*types.Receipt
uncles []*block.Header uncles []*block.Header
@ -184,9 +185,10 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if gen != nil { if gen != nil {
gen(i, b) gen(i, b)
} }
if b.engine != nil { if b.engine != nil {
// Finalize and seal the block // Finalize and seal the block
block, err := b.engine.Finalize(chainreader, b.header, statedb, b.txs, b.receipts, nil, nil) block, err := b.engine.Finalize(chainreader, b.header, statedb, b.txs, b.stkTxs, b.receipts, nil, nil)
if err != nil { if err != nil {
panic(err) panic(err)
} }

@ -19,6 +19,8 @@ package core
import ( import (
"fmt" "fmt"
"math" "math"
"github.com/harmony-one/harmony/core/values"
) )
// GasPool tracks the amount of gas available during execution of the transactions // GasPool tracks the amount of gas available during execution of the transactions
@ -38,7 +40,7 @@ func (gp *GasPool) AddGas(amount uint64) *GasPool {
// available and returns an error otherwise. // available and returns an error otherwise.
func (gp *GasPool) SubGas(amount uint64) error { func (gp *GasPool) SubGas(amount uint64) error {
if uint64(*gp) < amount { if uint64(*gp) < amount {
return ErrGasLimitReached return values.ErrGasLimitReached
} }
*(*uint64)(gp) -= amount *(*uint64)(gp) -= amount
return nil return nil

@ -1,4 +1,4 @@
package types package numeric
import ( import (
"encoding/json" "encoding/json"

@ -1,4 +1,4 @@
package types package numeric
import ( import (
"math/big" "math/big"

@ -9,8 +9,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/contracts/structs"
common2 "github.com/harmony-one/harmony/internal/common" common2 "github.com/harmony-one/harmony/internal/common"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding" shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
"github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"
@ -158,10 +156,7 @@ func GetShardingStateFromBlockChain(bc *BlockChain, epoch *big.Int) (*ShardingSt
} }
// CalculateNewShardState get sharding state from previous epoch and calculate sharding state for new epoch // CalculateNewShardState get sharding state from previous epoch and calculate sharding state for new epoch
func CalculateNewShardState( func CalculateNewShardState(bc *BlockChain, epoch *big.Int) (shard.State, error) {
bc *BlockChain, epoch *big.Int,
stakeInfo *map[common.Address]*structs.StakeInfo,
) (shard.State, error) {
if epoch.Cmp(big.NewInt(GenesisEpoch)) == 0 { if epoch.Cmp(big.NewInt(GenesisEpoch)) == 0 {
return CalculateInitShardState(), nil return CalculateInitShardState(), nil
} }
@ -171,42 +166,10 @@ func CalculateNewShardState(
return nil, ctxerror.New("cannot retrieve previous sharding state"). return nil, ctxerror.New("cannot retrieve previous sharding state").
WithCause(err) WithCause(err)
} }
newNodeList := ss.UpdateShardingState(stakeInfo)
utils.Logger().Info().Float64("percentage", CuckooRate).Msg("Cuckoo Rate") utils.Logger().Info().Float64("percentage", CuckooRate).Msg("Cuckoo Rate")
ss.Reshard(newNodeList, CuckooRate)
return ss.shardState, nil return ss.shardState, nil
} }
// UpdateShardingState remove the unstaked nodes and returns the newly staked node Ids.
func (ss *ShardingState) UpdateShardingState(stakeInfo *map[common.Address]*structs.StakeInfo) []shard.NodeID {
oldBlsPublicKeys := make(map[shard.BlsPublicKey]bool) // map of bls public keys
for _, shard := range ss.shardState {
newNodeList := shard.NodeList
for _, nodeID := range shard.NodeList {
oldBlsPublicKeys[nodeID.BlsPublicKey] = true
_, ok := (*stakeInfo)[nodeID.EcdsaAddress]
if ok {
// newNodeList = append(newNodeList, nodeID)
} else {
// TODO: Remove the node if it's no longer staked
}
}
shard.NodeList = newNodeList
}
newAddresses := []shard.NodeID{}
for addr, info := range *stakeInfo {
_, ok := oldBlsPublicKeys[info.BlsPublicKey]
if !ok {
newAddresses = append(newAddresses, shard.NodeID{
EcdsaAddress: addr,
BlsPublicKey: info.BlsPublicKey,
})
}
}
return newAddresses
}
// TODO ek – shardingSchedule should really be part of a general-purpose network // TODO ek – shardingSchedule should really be part of a general-purpose network
// configuration. We are OK for the time being, // configuration. We are OK for the time being,
// until the day we should let one node process join multiple networks. // until the day we should let one node process join multiple networks.

@ -21,7 +21,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
consensus_engine "github.com/harmony-one/harmony/consensus/engine" consensus_engine "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/state"
@ -30,6 +29,7 @@ import (
"github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
staking "github.com/harmony-one/harmony/staking/types"
) )
// StateProcessor is a basic Processor, which takes care of transitioning // StateProcessor is a basic Processor, which takes care of transitioning
@ -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) // Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
_, err := p.engine.Finalize(p.bc, header, statedb, block.Transactions(), receipts, outcxs, incxs) _, err := p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.StakingTransactions(), receipts, outcxs, incxs)
if err != nil { if err != nil {
return nil, nil, nil, 0, ctxerror.New("cannot finalize block").WithCause(err) return nil, nil, nil, 0, ctxerror.New("cannot finalize block").WithCause(err)
} }
@ -180,6 +180,18 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
return receipt, cxReceipt, gas, err return receipt, cxReceipt, gas, err
} }
// ApplyStakingTransaction attempts to apply a staking transaction to the given state database
// and uses the input parameters for its environment. It returns the receipt
// for the staking transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
// staking transaction will use the code field in the account to store the staking information
// TODO chao: Add receipts for staking tx
func ApplyStakingTransaction(
config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.DB,
header *block.Header, tx *staking.StakingTransaction, usedGas *uint64, cfg vm.Config) (receipt *types.Receipt, gasUsed uint64, oops error) {
return nil, 0, nil
}
// ApplyIncomingReceipt will add amount into ToAddress in the receipt // ApplyIncomingReceipt will add amount into ToAddress in the receipt
func ApplyIncomingReceipt(config *params.ChainConfig, db *state.DB, header *block.Header, cxp *types.CXReceiptsProof) error { func ApplyIncomingReceipt(config *params.ChainConfig, db *state.DB, header *block.Header, cxp *types.CXReceiptsProof) error {
if cxp == nil { if cxp == nil {

@ -22,9 +22,9 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/core/vm"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
) )
@ -171,9 +171,9 @@ func (st *StateTransition) preCheck() error {
nonce := st.state.GetNonce(st.msg.From()) nonce := st.state.GetNonce(st.msg.From())
if nonce < st.msg.Nonce() { if nonce < st.msg.Nonce() {
return ErrNonceTooHigh return values.ErrNonceTooHigh
} else if nonce > st.msg.Nonce() { } else if nonce > st.msg.Nonce() {
return ErrNonceTooLow return values.ErrNonceTooLow
} }
} }
return st.buyGas() return st.buyGas()

@ -18,7 +18,6 @@ package core
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
@ -30,11 +29,11 @@ import (
"github.com/ethereum/go-ethereum/common/prque" "github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
) )
@ -43,44 +42,6 @@ const (
chainHeadChanSize = 10 chainHeadChanSize = 10
) )
var (
// ErrInvalidSender is returned if the transaction contains an invalid signature.
ErrInvalidSender = errors.New("invalid sender")
// ErrNonceTooLow is returned if the nonce of a transaction is lower than the
// one present in the local chain.
ErrNonceTooLow = errors.New("nonce too low")
// ErrUnderpriced is returned if a transaction's gas price is below the minimum
// configured for the transaction pool.
ErrUnderpriced = errors.New("transaction underpriced")
// ErrReplaceUnderpriced is returned if a transaction is attempted to be replaced
// with a different one without the required price bump.
ErrReplaceUnderpriced = errors.New("replacement transaction underpriced")
// ErrInsufficientFunds is returned if the total cost of executing a transaction
// is higher than the balance of the user's account.
ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value")
// ErrIntrinsicGas is returned if the transaction is specified to use less gas
// than required to start the invocation.
ErrIntrinsicGas = errors.New("intrinsic gas too low")
// ErrGasLimit is returned if a transaction's requested gas limit exceeds the
// maximum allowance of the current block.
ErrGasLimit = errors.New("exceeds block gas limit")
// ErrNegativeValue is a sanity error to ensure noone is able to specify a
// transaction with a negative value.
ErrNegativeValue = errors.New("negative value")
// ErrOversizedData is returned if the input data of a transaction is greater
// than some meaningful limit a user might use. This is not a consensus error
// making the transaction invalid, rather a DOS protection.
ErrOversizedData = errors.New("oversized data")
)
var ( var (
evictionInterval = time.Minute // Time interval to check for evictable transactions evictionInterval = time.Minute // Time interval to check for evictable transactions
statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats
@ -602,42 +563,42 @@ func (pool *TxPool) local() map[common.Address]types.Transactions {
func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
// Heuristic limit, reject transactions over 32KB to prevent DOS attacks // Heuristic limit, reject transactions over 32KB to prevent DOS attacks
if tx.Size() > 32*1024 { if tx.Size() > 32*1024 {
return ErrOversizedData return values.ErrOversizedData
} }
// Transactions can't be negative. This may never happen using RLP decoded // Transactions can't be negative. This may never happen using RLP decoded
// transactions but may occur if you create a transaction using the RPC. // transactions but may occur if you create a transaction using the RPC.
if tx.Value().Sign() < 0 { if tx.Value().Sign() < 0 {
return ErrNegativeValue return values.ErrNegativeValue
} }
// Ensure the transaction doesn't exceed the current block limit gas. // Ensure the transaction doesn't exceed the current block limit gas.
if pool.currentMaxGas < tx.Gas() { if pool.currentMaxGas < tx.Gas() {
return ErrGasLimit return values.ErrGasLimit
} }
// Make sure the transaction is signed properly // Make sure the transaction is signed properly
from, err := types.Sender(pool.signer, tx) from, err := types.Sender(pool.signer, tx)
if err != nil { if err != nil {
return ErrInvalidSender return values.ErrInvalidSender
} }
// Drop non-local transactions under our own minimal accepted gas price // Drop non-local transactions under our own minimal accepted gas price
local = local || pool.locals.contains(from) // account may be local even if the transaction arrived from the network local = local || pool.locals.contains(from) // account may be local even if the transaction arrived from the network
if !local && pool.gasPrice.Cmp(tx.GasPrice()) > 0 { if !local && pool.gasPrice.Cmp(tx.GasPrice()) > 0 {
return ErrUnderpriced return values.ErrUnderpriced
} }
// Ensure the transaction adheres to nonce ordering // Ensure the transaction adheres to nonce ordering
if pool.currentState.GetNonce(from) > tx.Nonce() { if pool.currentState.GetNonce(from) > tx.Nonce() {
return ErrNonceTooLow return values.ErrNonceTooLow
} }
// Transactor should have enough funds to cover the costs // Transactor should have enough funds to cover the costs
// cost == V + GP * GL // cost == V + GP * GL
if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
return ErrInsufficientFunds return values.ErrInsufficientFunds
} }
intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead) intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
if err != nil { if err != nil {
return err return err
} }
if tx.Gas() < intrGas { if tx.Gas() < intrGas {
return ErrIntrinsicGas return values.ErrIntrinsicGas
} }
return nil return nil
} }
@ -673,7 +634,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
Str("price", tx.GasPrice().String()). Str("price", tx.GasPrice().String()).
Msg("Discarding underpriced transaction") Msg("Discarding underpriced transaction")
underpricedTxCounter.Inc(1) underpricedTxCounter.Inc(1)
return false, ErrUnderpriced return false, values.ErrUnderpriced
} }
// New transaction is better than our worse ones, make room for it // New transaction is better than our worse ones, make room for it
drop := pool.priced.Discard(pool.all.Count()-int(pool.config.GlobalSlots+pool.config.GlobalQueue-1), pool.locals) drop := pool.priced.Discard(pool.all.Count()-int(pool.config.GlobalSlots+pool.config.GlobalQueue-1), pool.locals)
@ -693,7 +654,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
inserted, old := list.Add(tx, pool.config.PriceBump) inserted, old := list.Add(tx, pool.config.PriceBump)
if !inserted { if !inserted {
pendingDiscardCounter.Inc(1) pendingDiscardCounter.Inc(1)
return false, ErrReplaceUnderpriced return false, values.ErrReplaceUnderpriced
} }
// New transaction is better, replace old one // New transaction is better, replace old one
if old != nil { if old != nil {
@ -759,7 +720,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) (bool, er
if !inserted { if !inserted {
// An older transaction was better, discard this // An older transaction was better, discard this
queuedDiscardCounter.Inc(1) queuedDiscardCounter.Inc(1)
return false, ErrReplaceUnderpriced return false, values.ErrReplaceUnderpriced
} }
// Discard any previous transaction and mark this // Discard any previous transaction and mark this
if old != nil { if old != nil {

@ -30,11 +30,11 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
blockfactory "github.com/harmony-one/harmony/block/factory" blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/common/denominations" "github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
) )
@ -235,27 +235,27 @@ func TestInvalidTransactions(t *testing.T) {
from, _ := deriveSender(tx) from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1)) pool.currentState.AddBalance(from, big.NewInt(1))
if err := pool.AddRemote(tx); err != ErrInsufficientFunds { if err := pool.AddRemote(tx); err != values.ErrInsufficientFunds {
t.Error("expected", ErrInsufficientFunds) t.Error("expected", values.ErrInsufficientFunds)
} }
balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()))
pool.currentState.AddBalance(from, balance) pool.currentState.AddBalance(from, balance)
if err := pool.AddRemote(tx); err != ErrIntrinsicGas { if err := pool.AddRemote(tx); err != values.ErrIntrinsicGas {
t.Error("expected", ErrIntrinsicGas, "got", err) t.Error("expected", values.ErrIntrinsicGas, "got", err)
} }
pool.currentState.SetNonce(from, 1) pool.currentState.SetNonce(from, 1)
pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff)) pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
tx = transaction(0, 100000, key) tx = transaction(0, 100000, key)
if err := pool.AddRemote(tx); err != ErrNonceTooLow { if err := pool.AddRemote(tx); err != values.ErrNonceTooLow {
t.Error("expected", ErrNonceTooLow) t.Error("expected", values.ErrNonceTooLow)
} }
tx = transaction(1, 100000, key) tx = transaction(1, 100000, key)
pool.gasPrice = big.NewInt(1000) pool.gasPrice = big.NewInt(1000)
if err := pool.AddRemote(tx); err != ErrUnderpriced { if err := pool.AddRemote(tx); err != values.ErrUnderpriced {
t.Error("expected", ErrUnderpriced, "got", err) t.Error("expected", values.ErrUnderpriced, "got", err)
} }
if err := pool.AddLocal(tx); err != nil { if err := pool.AddLocal(tx); err != nil {
t.Error("expected", nil, "got", err) t.Error("expected", nil, "got", err)
@ -325,8 +325,8 @@ func TestTransactionNegativeValue(t *testing.T) {
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, 0, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, 0, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key)
from, _ := deriveSender(tx) from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1)) pool.currentState.AddBalance(from, big.NewInt(1))
if err := pool.AddRemote(tx); err != ErrNegativeValue { if err := pool.AddRemote(tx); err != values.ErrNegativeValue {
t.Error("expected", ErrNegativeValue, "got", err) t.Error("expected", values.ErrNegativeValue, "got", err)
} }
} }

@ -30,10 +30,6 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/taggedrlp"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
blockfactory "github.com/harmony-one/harmony/block/factory" blockfactory "github.com/harmony-one/harmony/block/factory"
v0 "github.com/harmony-one/harmony/block/v0" v0 "github.com/harmony-one/harmony/block/v0"
@ -42,6 +38,10 @@ import (
"github.com/harmony-one/harmony/crypto/hash" "github.com/harmony-one/harmony/crypto/hash"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
"github.com/harmony-one/taggedrlp"
"github.com/pkg/errors"
"github.com/rs/zerolog"
) )
// Constants for block. // Constants for block.
@ -181,11 +181,12 @@ func init() {
BodyRegistry.MustRegister("v1", new(BodyV1)) BodyRegistry.MustRegister("v1", new(BodyV1))
} }
// Block represents an entire block in the Ethereum blockchain. // Block represents an entire block in the Harmony blockchain.
type Block struct { type Block struct {
header *block.Header header *block.Header
uncles []*block.Header uncles []*block.Header
transactions Transactions transactions Transactions
stakingTransactions staking.StakingTransactions
incomingReceipts CXReceiptsProofs incomingReceipts CXReceiptsProofs
// caches // caches
@ -347,6 +348,11 @@ func (b *Block) Transactions() Transactions {
return b.transactions return b.transactions
} }
// StakingTransactions returns stakingTransactions.
func (b *Block) StakingTransactions() staking.StakingTransactions {
return b.stakingTransactions
}
// IncomingReceipts returns verified outgoing receipts // IncomingReceipts returns verified outgoing receipts
func (b *Block) IncomingReceipts() CXReceiptsProofs { func (b *Block) IncomingReceipts() CXReceiptsProofs {
return b.incomingReceipts return b.incomingReceipts

@ -0,0 +1,10 @@
package values
const (
// BeaconChainShardID is the ShardID of the BeaconChain
BeaconChainShardID = 0
// VotingPowerReduceBlockThreshold roughly corresponds to 3 hours
VotingPowerReduceBlockThreshold = 1350
// VotingPowerFullReduce roughly corresponds to 12 hours
VotingPowerFullReduce = 4 * VotingPowerReduceBlockThreshold
)

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package values
import ( import (
"github.com/pkg/errors" "github.com/pkg/errors"
@ -31,6 +31,10 @@ var (
// ErrBlacklistedHash is returned if a block to import is on the blacklist. // ErrBlacklistedHash is returned if a block to import is on the blacklist.
ErrBlacklistedHash = errors.New("blacklisted hash") ErrBlacklistedHash = errors.New("blacklisted hash")
// ErrNonceTooLow is returned if the nonce of a transaction is lower than the
// one present in the local chain.
ErrNonceTooLow = errors.New("nonce too low")
// ErrNonceTooHigh is returned if the nonce of a transaction is higher than the // ErrNonceTooHigh is returned if the nonce of a transaction is higher than the
// next one expected based on the local chain. // next one expected based on the local chain.
ErrNonceTooHigh = errors.New("nonce too high") ErrNonceTooHigh = errors.New("nonce too high")
@ -40,4 +44,36 @@ var (
// ErrInvalidChainID when ChainID of signer does not match that of running node // ErrInvalidChainID when ChainID of signer does not match that of running node
ErrInvalidChainID = errors.New("invalid chain id for signer") ErrInvalidChainID = errors.New("invalid chain id for signer")
// ErrInvalidSender is returned if the transaction contains an invalid signature.
ErrInvalidSender = errors.New("invalid sender")
// ErrUnderpriced is returned if a transaction's gas price is below the minimum
// configured for the transaction pool.
ErrUnderpriced = errors.New("transaction underpriced")
// ErrReplaceUnderpriced is returned if a transaction is attempted to be replaced
// with a different one without the required price bump.
ErrReplaceUnderpriced = errors.New("replacement transaction underpriced")
// ErrInsufficientFunds is returned if the total cost of executing a transaction
// is higher than the balance of the user's account.
ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value")
// ErrIntrinsicGas is returned if the transaction is specified to use less gas
// than required to start the invocation.
ErrIntrinsicGas = errors.New("intrinsic gas too low")
// ErrGasLimit is returned if a transaction's requested gas limit exceeds the
// maximum allowance of the current block.
ErrGasLimit = errors.New("exceeds block gas limit")
// ErrNegativeValue is a sanity error to ensure noone is able to specify a
// transaction with a negative value.
ErrNegativeValue = errors.New("negative value")
// ErrOversizedData is returned if the input data of a transaction is greater
// than some meaningful limit a user might use. This is not a consensus error
// making the transaction invalid, rather a DOS protection.
ErrOversizedData = errors.New("oversized data")
) )

@ -6,9 +6,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/pkg/errors"
"golang.org/x/crypto/sha3"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/consensus/engine" "github.com/harmony-one/harmony/consensus/engine"
"github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core"
@ -17,6 +14,9 @@ import (
"github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
"github.com/pkg/errors"
"golang.org/x/crypto/sha3"
) )
type engineImpl struct{} type engineImpl struct{}
@ -149,7 +149,11 @@ func (e *engineImpl) VerifySeal(chain engine.ChainReader, header *block.Header)
// Finalize implements Engine, accumulating the block rewards, // Finalize implements Engine, accumulating the block rewards,
// setting the final state and assembling the block. // setting the final state and assembling the block.
func (e *engineImpl) Finalize(chain engine.ChainReader, header *block.Header, state *state.DB, txs []*types.Transaction, receipts []*types.Receipt, outcxs []*types.CXReceipt, incxs []*types.CXReceiptsProof) (*types.Block, error) { 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) {
// Accumulate any block and uncle rewards and commit the final state root // Accumulate any block and uncle rewards and commit the final state root
// Header seems complete, assemble into a block and return // Header seems complete, assemble into a block and return
if err := AccumulateRewards(chain, state, header); err != nil { if err := AccumulateRewards(chain, state, header); err != nil {

@ -5,7 +5,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/common/denominations" "github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/consensus/engine" "github.com/harmony-one/harmony/consensus/engine"
@ -85,6 +84,7 @@ func AccumulateRewards(
accounts = append(accounts, member.EcdsaAddress) accounts = append(accounts, member.EcdsaAddress)
} }
} }
numAccounts := big.NewInt(int64(len(accounts))) numAccounts := big.NewInt(int64(len(accounts)))
last := new(big.Int) last := new(big.Int)
for i, account := range accounts { for i, account := range accounts {

@ -9,9 +9,9 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/harmony/accounts" "github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/rawdb" "github.com/harmony-one/harmony/core/rawdb"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/values"
internal_common "github.com/harmony-one/harmony/internal/common" internal_common "github.com/harmony-one/harmony/internal/common"
staking "github.com/harmony-one/harmony/staking/types" staking "github.com/harmony-one/harmony/staking/types"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -179,7 +179,7 @@ func (s *PublicTransactionPoolAPI) SendRawStakingTransaction(
} }
c := s.b.ChainConfig().ChainID c := s.b.ChainConfig().ChainID
if tx.ChainID().Cmp(c) != 0 { if tx.ChainID().Cmp(c) != 0 {
e := errors.Wrapf(core.ErrInvalidChainID, "current chain id:%s", c.String()) e := errors.Wrapf(values.ErrInvalidChainID, "current chain id:%s", c.String())
return common.Hash{}, e return common.Hash{}, e
} }
return SubmitStakingTransaction(ctx, s.b, tx) return SubmitStakingTransaction(ctx, s.b, tx)
@ -194,7 +194,7 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod
} }
c := s.b.ChainConfig().ChainID c := s.b.ChainConfig().ChainID
if tx.ChainID().Cmp(c) != 0 { if tx.ChainID().Cmp(c) != 0 {
e := errors.Wrapf(core.ErrInvalidChainID, "current chain id:%s", c.String()) e := errors.Wrapf(values.ErrInvalidChainID, "current chain id:%s", c.String())
return common.Hash{}, e return common.Hash{}, e
} }
return SubmitTransaction(ctx, s.b, tx) return SubmitTransaction(ctx, s.b, tx)

@ -20,6 +20,7 @@ import (
"github.com/harmony-one/harmony/contracts" "github.com/harmony-one/harmony/contracts"
"github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/drand" "github.com/harmony-one/harmony/drand"
"github.com/harmony-one/harmony/internal/chain" "github.com/harmony-one/harmony/internal/chain"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node" nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
@ -372,7 +373,8 @@ func (node *Node) getTransactionsForNewBlock(
} }
selected, unselected, invalid := node.Worker.SelectTransactionsForNewBlock(newBlockNum, pendingTransactions, node.recentTxsStats, txsThrottleConfig, coinbase) selected, unselected, invalid := node.Worker.SelectTransactionsForNewBlock(newBlockNum, pendingTransactions, node.recentTxsStats, txsThrottleConfig, coinbase)
selectedStaking, unselectedStaking, invalidStaking := node.Worker.SelectStakingTransactionsForNewBlock(newBlockNum, pendingStakingTransactions, node.recentTxsStats, txsThrottleConfig, coinbase) selectedStaking, unselectedStaking, invalidStaking :=
node.Worker.SelectStakingTransactionsForNewBlock(newBlockNum, pendingStakingTransactions, coinbase)
node.pendingTransactions = make(map[common.Hash]*types.Transaction) node.pendingTransactions = make(map[common.Hash]*types.Transaction)
for _, unselectedTx := range unselected { for _, unselectedTx := range unselected {
@ -465,14 +467,14 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, chainDBFactory shardc
node.TxPool = core.NewTxPool(core.DefaultTxPoolConfig, node.Blockchain().Config(), blockchain) node.TxPool = core.NewTxPool(core.DefaultTxPoolConfig, node.Blockchain().Config(), blockchain)
node.CxPool = core.NewCxPool(core.CxPoolSize) node.CxPool = core.NewCxPool(core.CxPoolSize)
node.Worker = worker.New(node.Blockchain().Config(), blockchain, chain.Engine) node.Worker = worker.New(node.Blockchain().Config(), blockchain, chain.Engine)
if node.Blockchain().ShardID() != 0 {
if node.Blockchain().ShardID() != values.BeaconChainShardID {
node.BeaconWorker = worker.New(node.Beaconchain().Config(), beaconChain, chain.Engine) node.BeaconWorker = worker.New(node.Beaconchain().Config(), beaconChain, chain.Engine)
} }
node.pendingCXReceipts = make(map[string]*types.CXReceiptsProof) node.pendingCXReceipts = make(map[string]*types.CXReceiptsProof)
node.pendingTransactions = make(map[common.Hash]*types.Transaction) node.pendingTransactions = make(map[common.Hash]*types.Transaction)
node.pendingStakingTransactions = make(map[common.Hash]*staking.StakingTransaction) node.pendingStakingTransactions = make(map[common.Hash]*staking.StakingTransaction)
node.Consensus.VerifiedNewBlock = make(chan *types.Block) node.Consensus.VerifiedNewBlock = make(chan *types.Block)
// the sequence number is the next block number to be added in consensus protocol, which is always one more than current chain header block // the sequence number is the next block number to be added in consensus protocol, which is always one more than current chain header block
node.Consensus.SetBlockNum(blockchain.CurrentBlock().NumberU64() + 1) node.Consensus.SetBlockNum(blockchain.CurrentBlock().NumberU64() + 1)
@ -486,20 +488,7 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, chainDBFactory shardc
} else { } else {
node.AddContractKeyAndAddress(scFaucet) node.AddContractKeyAndAddress(scFaucet)
} }
//if node.Consensus.ShardID == 0 {
// // Contracts only exist in beacon chain
// if node.isFirstTime {
// // Setup one time smart contracts
// node.CurrentStakes = make(map[common.Address]*structs.StakeInfo)
// node.AddStakingContractToPendingTransactions() //This will save the latest information about staked nodes in current staked
// } else {
// node.AddContractKeyAndAddress(scStaking)
// }
//}
node.ContractCaller = contracts.NewContractCaller(node.Blockchain(), node.Blockchain().Config()) node.ContractCaller = contracts.NewContractCaller(node.Blockchain(), node.Blockchain().Config())
// Create test keys. Genesis will later need this. // Create test keys. Genesis will later need this.
var err error var err error
node.TestBankKeys, err = CreateTestBankKeys(TestAccountNumber) node.TestBankKeys, err = CreateTestBankKeys(TestAccountNumber)

@ -151,8 +151,7 @@ func (node *Node) proposeBeaconShardState(block *types.Block) error {
} }
nextEpoch := new(big.Int).Add(block.Header().Epoch(), common.Big1) nextEpoch := new(big.Int).Add(block.Header().Epoch(), common.Big1)
// TODO: add logic for EPoS // TODO: add logic for EPoS
shardState, err := core.CalculateNewShardState( shardState, err := core.CalculateNewShardState(node.Blockchain(), nextEpoch)
node.Blockchain(), nextEpoch, nil)
if err != nil { if err != nil {
return err return err
} }

@ -9,14 +9,11 @@ import (
"os/exec" "os/exec"
"strconv" "strconv"
"syscall" "syscall"
"time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/contracts/structs"
"time"
proto_node "github.com/harmony-one/harmony/api/proto/node" proto_node "github.com/harmony-one/harmony/api/proto/node"
"github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
@ -28,7 +25,7 @@ import (
) )
// validateNewShardState validate whether the new shard state root matches // validateNewShardState validate whether the new shard state root matches
func (node *Node) validateNewShardState(block *types.Block, stakeInfo *map[common.Address]*structs.StakeInfo) error { func (node *Node) validateNewShardState(block *types.Block) error {
// Common case first – blocks without resharding proposal // Common case first – blocks without resharding proposal
header := block.Header() header := block.Header()
if header.ShardStateHash() == (common.Hash{}) { if header.ShardStateHash() == (common.Hash{}) {
@ -61,8 +58,7 @@ func (node *Node) validateNewShardState(block *types.Block, stakeInfo *map[commo
// TODO ek – this may be called from regular shards, // TODO ek – this may be called from regular shards,
// for vetting beacon chain blocks received during block syncing. // for vetting beacon chain blocks received during block syncing.
// DRand may or or may not get in the way. Test this out. // DRand may or or may not get in the way. Test this out.
expected, err := core.CalculateNewShardState( expected, err := core.CalculateNewShardState(node.Blockchain(), nextEpoch)
node.Blockchain(), nextEpoch, stakeInfo)
if err != nil { if err != nil {
return ctxerror.New("cannot calculate expected shard state"). return ctxerror.New("cannot calculate expected shard state").
WithCause(err) WithCause(err)

@ -13,6 +13,7 @@ import (
"github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/core/vm"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding" shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
"github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"
@ -29,6 +30,7 @@ type environment struct {
header *block.Header header *block.Header
txs []*types.Transaction txs []*types.Transaction
stkingTxs staking.StakingTransactions
receipts []*types.Receipt receipts []*types.Receipt
outcxs []*types.CXReceipt // cross shard transaction receipts (source shard) outcxs []*types.CXReceipt // cross shard transaction receipts (source shard)
incxs []*types.CXReceiptsProof // cross shard receipts and its proof (desitinatin shard) incxs []*types.CXReceiptsProof // cross shard receipts and its proof (desitinatin shard)
@ -146,12 +148,58 @@ func (w *Worker) SelectTransactionsForNewBlock(newBlockNum uint64, txs types.Tra
// SelectStakingTransactionsForNewBlock selects staking transactions for new block. // SelectStakingTransactionsForNewBlock selects staking transactions for new block.
func (w *Worker) SelectStakingTransactionsForNewBlock( func (w *Worker) SelectStakingTransactionsForNewBlock(
newBlockNum uint64, txs staking.StakingTransactions, newBlockNum uint64, txs staking.StakingTransactions,
recentTxsStats types.RecentTxsStats,
txsThrottleConfig *shardingconfig.TxsThrottleConfig,
coinbase common.Address) (staking.StakingTransactions, staking.StakingTransactions, staking.StakingTransactions) { coinbase common.Address) (staking.StakingTransactions, staking.StakingTransactions, staking.StakingTransactions) {
// TODO: implement staking transaction selection
t := staking.StakingTransactions{} // only beaconchain process staking transaction
return t, t, t 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) { func (w *Worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) {
@ -348,7 +396,9 @@ func (w *Worker) FinalizeNewBlock(sig []byte, signers []byte, viewID uint64, coi
s := w.current.state.Copy() s := w.current.state.Copy()
copyHeader := types.CopyHeader(w.current.header) copyHeader := types.CopyHeader(w.current.header)
block, err := w.engine.Finalize(w.chain, copyHeader, s, w.current.txs, w.current.receipts, w.current.outcxs, w.current.incxs) block, err := w.engine.Finalize(
w.chain, copyHeader, s, w.current.txs, w.current.stkingTxs, w.current.receipts, w.current.outcxs, w.current.incxs,
)
if err != nil { if err != nil {
return nil, ctxerror.New("cannot finalize block").WithCause(err) return nil, ctxerror.New("cannot finalize block").WithCause(err)
} }

@ -7,10 +7,9 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"golang.org/x/crypto/sha3"
common2 "github.com/harmony-one/harmony/internal/common" common2 "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"
"golang.org/x/crypto/sha3"
) )
var ( var (
@ -101,7 +100,7 @@ func CompareBlsPublicKey(k1, k2 BlsPublicKey) int {
return bytes.Compare(k1[:], k2[:]) return bytes.Compare(k1[:], k2[:])
} }
// NodeID represents node id (BLS address). // NodeID represents node id (BLS address) and its voting power, which is set at epoch change only.
type NodeID struct { type NodeID struct {
EcdsaAddress common.Address `json:"ecdsa_address"` EcdsaAddress common.Address `json:"ecdsa_address"`
BlsPublicKey BlsPublicKey `json:"bls_pubkey"` BlsPublicKey BlsPublicKey `json:"bls_pubkey"`

@ -2,6 +2,8 @@ package types
import ( import (
"math/big" "math/big"
"github.com/harmony-one/harmony/core/numeric"
) )
type ( type (
@ -15,14 +17,8 @@ type (
// CommissionRates defines the initial commission rates to be used for creating a // CommissionRates defines the initial commission rates to be used for creating a
// validator. // validator.
CommissionRates struct { CommissionRates struct {
Rate Dec `json:"rate" yaml:"rate"` // the commission rate charged to delegators, as a fraction Rate numeric.Dec `json:"rate" yaml:"rate"` // the commission rate charged to delegators, as a fraction
MaxRate Dec `json:"max_rate" yaml:"max_rate"` // maximum commission rate which validator can ever charge, as a fraction MaxRate numeric.Dec `json:"max_rate" yaml:"max_rate"` // maximum commission rate which validator can ever charge, as a fraction
MaxChangeRate Dec `json:"max_change_rate" yaml:"max_change_rate"` // maximum increase of the validator commission every epoch, as a fraction MaxChangeRate numeric.Dec `json:"max_change_rate" yaml:"max_change_rate"` // maximum increase of the validator commission every epoch, as a fraction
} }
) )
// NewCommission returns a new commission object
func NewCommission(rate Dec, maxRate Dec, maxChangeRate Dec, height *big.Int) Commission {
commissionRates := CommissionRates{Rate: rate, MaxRate: maxRate, MaxChangeRate: maxChangeRate}
return Commission{CommissionRates: commissionRates, UpdateHeight: height}
}

@ -3,6 +3,7 @@ package types
import ( import (
"math/big" "math/big"
"github.com/harmony-one/harmony/core/numeric"
"github.com/harmony-one/harmony/internal/common" "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -38,7 +39,7 @@ func (d Directive) String() string {
// NewValidator - type for creating a new validator // NewValidator - type for creating a new validator
type NewValidator struct { type NewValidator struct {
Description `json:"ties" yaml:"ties"` Description `json:"description" yaml:"description"`
CommissionRates `json:"commission" yaml:"commission"` CommissionRates `json:"commission" yaml:"commission"`
MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"` MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"`
StakingAddress common.Address `json:"staking_address" yaml:"staking_address"` StakingAddress common.Address `json:"staking_address" yaml:"staking_address"`
@ -50,7 +51,7 @@ type NewValidator struct {
type EditValidator struct { type EditValidator struct {
Description Description
StakingAddress common.Address `json:"staking_address" yaml:"staking_address"` StakingAddress common.Address `json:"staking_address" yaml:"staking_address"`
CommissionRate Dec `json:"commission_rate" yaml:"commission_rate"` CommissionRate numeric.Dec `json:"commission_rate" yaml:"commission_rate"`
MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"` MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"`
} }

@ -24,7 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core/values"
"github.com/harmony-one/harmony/crypto/hash" "github.com/harmony-one/harmony/crypto/hash"
) )
@ -111,7 +111,7 @@ var big8 = big.NewInt(8)
// Sender returns the sender address of the given signer. // Sender returns the sender address of the given signer.
func (s EIP155Signer) Sender(tx *StakingTransaction) (common.Address, error) { func (s EIP155Signer) Sender(tx *StakingTransaction) (common.Address, error) {
if tx.ChainID().Cmp(s.chainID) != 0 { if tx.ChainID().Cmp(s.chainID) != 0 {
return common.Address{}, core.ErrInvalidChainID return common.Address{}, values.ErrInvalidChainID
} }
V := new(big.Int).Sub(tx.data.V, s.chainIDMul) V := new(big.Int).Sub(tx.data.V, s.chainIDMul)
V.Sub(V, big8) V.Sub(V, big8)

@ -86,6 +86,11 @@ func (tx *StakingTransaction) WithSignature(signer Signer, sig []byte) (*Staking
return cpy, nil return cpy, nil
} }
// Gas returns gas of StakingTransaction.
func (tx *StakingTransaction) Gas() uint64 {
return tx.data.GasLimit
}
// ChainID is what chain this staking transaction for // ChainID is what chain this staking transaction for
func (tx *StakingTransaction) ChainID() *big.Int { func (tx *StakingTransaction) ChainID() *big.Int {
return deriveChainID(tx.data.V) return deriveChainID(tx.data.V)

@ -18,14 +18,22 @@ const (
// Validator - data fields for a validator // Validator - data fields for a validator
type Validator struct { type Validator struct {
Address common.Address `json:"address" yaml:"address"` // ECDSA address of the validator // ECDSA address of the validator
ValidatingPubKey bls.PublicKey `json:"validating_pub_key" yaml:"validating_pub_key"` // The BLS public key of the validator for consensus Address common.Address `json:"address" yaml:"address"`
Description Description `json:"description" yaml:"description"` // description for the validator // The BLS public key of the validator for consensus
Active bool `json:"active" yaml:"active"` // Is the validator active in the validating process or not ValidatingPubKey bls.PublicKey `json:"validating_pub_key" yaml:"validating_pub_key"`
Stake *big.Int `json:"stake" yaml:"stake"` // The stake put by the validator itself // The stake put by the validator itself
UnbondingHeight *big.Int `json:"unbonding_height" yaml:"unbonding_height"` // if unbonding, height at which this validator has begun unbonding Stake *big.Int `json:"stake" yaml:"stake"`
Commission Commission `json:"commission" yaml:"commission"` // commission parameters // if unbonding, height at which this validator has begun unbonding
MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"` // validator's self declared minimum self delegation UnbondingHeight *big.Int `json:"unbonding_height" yaml:"unbonding_height"`
// validator's self declared minimum self delegation
MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"`
// commission parameters
Commission `json:"commission" yaml:"commission"`
// description for the validator
Description `json:"description" yaml:"description"`
// Is the validator active in the validating process or not
IsCurrentlyActive bool `json:"active" yaml:"active"`
} }
// Description - some possible IRL connections // Description - some possible IRL connections

Loading…
Cancel
Save