Merge remote-tracking branch 'origin/master' into t3

pull/3118/head
Leo Chen 5 years ago
commit edf69ed841
  1. 21
      README.md
  2. 53
      api/proto/node/node.go
  3. 18
      api/service/manager.go
  4. 18
      api/service/networkinfo/service.go
  5. 1
      consensus/consensus.go
  6. 30
      consensus/consensus_service.go
  7. 15
      consensus/consensus_v2.go
  8. 8
      consensus/view_change.go
  9. 16
      core/tx_list.go
  10. 37
      core/tx_pool.go
  11. 39
      hmy/api_backend.go
  12. 2
      internal/hmyapi/apiv1/backend.go
  13. 98
      internal/hmyapi/apiv1/blockchain.go
  14. 54
      internal/hmyapi/apiv1/types.go
  15. 2
      internal/hmyapi/apiv2/backend.go
  16. 98
      internal/hmyapi/apiv2/blockchain.go
  17. 56
      internal/hmyapi/apiv2/types.go
  18. 2
      internal/hmyapi/backend.go
  19. 2
      node/node.go
  20. 2
      scripts/node.sh
  21. 4
      staking/types/validator.go
  22. 1
      test/debug.sh
  23. 21
      test/deploy.sh

@ -38,8 +38,8 @@ $ git reset --hard origin/master
``` ```
$ git fetch $ git fetch
$ git checkout s3 $ git checkout t3
$ git reset --hard origin/s3 $ git reset --hard origin/t3
``` ```
And now run the local blockchain And now run the local blockchain
@ -118,13 +118,20 @@ $ eval $(gimme 1.14.1)
Note that changing the go version might mean that dependencies won't work out right when trying to Note that changing the go version might mean that dependencies won't work out right when trying to
run `test/debug.sh` again, get the correct environment again easily by `exec bash`. run `test/debug.sh` again, get the correct environment again easily by `exec bash`.
## Installation Requirements for directly on your machine ## Installation Requirements for directly on your MacOS X
GMP and OpenSSL GMP and OpenSSL
```bash ```bash
brew install gmp brew install gmp
brew install openssl brew install openssl
```
## On Linux Box (assuming Amazon Linux 2 or Cent OS)
```bash
sudo yum install glibc-static gmp-devel gmp-static openssl-libs openssl-static gcc-c++
``` ```
## Dev Environment Setup ## Dev Environment Setup
@ -243,11 +250,9 @@ See [`CONTRIBUTING`](CONTRIBUTING.md) for details.
- EPoS staking mechanism - EPoS staking mechanism
- Kademlia routing - Kademlia routing
### Features To Be Implemented ### Features Planned after Mainnet Open Staking
- Leader rotation
### Features Planned after Mainnet
- Resharding
- Integration with WASM - Integration with WASM
- Fast state synchronization - Fast state synchronization
- Auditable privacy asset using ZK proof

@ -2,10 +2,8 @@ package node
import ( import (
"bytes" "bytes"
"fmt"
"log" "log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/api/proto" "github.com/harmony-one/harmony/api/proto"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
@ -14,7 +12,6 @@ import (
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/staking/slash" "github.com/harmony-one/harmony/staking/slash"
staking "github.com/harmony-one/harmony/staking/types" staking "github.com/harmony-one/harmony/staking/types"
libp2p_peer "github.com/libp2p/go-libp2p-core/peer"
) )
// MessageType is to indicate the specific type of message under Node category // MessageType is to indicate the specific type of message under Node category
@ -31,22 +28,6 @@ const (
Staking Staking
) )
// BlockchainSyncMessage is a struct for blockchain sync message.
type BlockchainSyncMessage struct {
BlockHeight int
BlockHashes []common.Hash
}
// BlockchainSyncMessageType represents BlockchainSyncMessageType type.
type BlockchainSyncMessageType int
// Constant of blockchain sync-up message subtype
const (
Done BlockchainSyncMessageType = iota
GetLastBlockHashes
GetBlock
)
// TransactionMessageType representa the types of messages used for Node/Transaction // TransactionMessageType representa the types of messages used for Node/Transaction
type TransactionMessageType int type TransactionMessageType int
@ -56,40 +37,6 @@ const (
Unlock Unlock
) )
// RoleType defines the role of the node
type RoleType int
// Type of roles of a node
const (
ValidatorRole RoleType = iota
ClientRole
)
func (r RoleType) String() string {
switch r {
case ValidatorRole:
return "Validator"
case ClientRole:
return "Client"
}
return "Unknown"
}
// Info refers to Peer struct in p2p/peer.go
// this is basically a simplified version of Peer
// for network transportation
type Info struct {
IP string
Port string
PubKey []byte
Role RoleType
PeerID libp2p_peer.ID // Peerstore ID
}
func (info Info) String() string {
return fmt.Sprintf("Info:%v/%v=>%v", info.IP, info.Port, info.PeerID.Pretty())
}
// BlockMessageType represents the type of messages used for Node/Block // BlockMessageType represents the type of messages used for Node/Block
type BlockMessageType int type BlockMessageType int

@ -1,8 +1,6 @@
package service package service
import ( import (
"time"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
msg_pb "github.com/harmony-one/harmony/api/proto/message" msg_pb "github.com/harmony-one/harmony/api/proto/message"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
@ -28,7 +26,6 @@ const (
Consensus Consensus
BlockProposal BlockProposal
NetworkInfo NetworkInfo
PeerDiscovery
) )
func (t Type) String() string { func (t Type) String() string {
@ -43,19 +40,11 @@ func (t Type) String() string {
return "BlockProposal" return "BlockProposal"
case NetworkInfo: case NetworkInfo:
return "NetworkInfo" return "NetworkInfo"
case PeerDiscovery:
return "PeerDiscovery"
default: default:
return "Unknown" return "Unknown"
} }
} }
// Constants for timing.
const (
// WaitForStatusUpdate is the delay time to update new status. Currently set 1 second for development. Should be 30 minutes for production.
WaitForStatusUpdate = time.Minute * 1
)
// Action is type of service action. // Action is type of service action.
type Action struct { type Action struct {
Action ActionType Action ActionType
@ -114,11 +103,6 @@ func (m *Manager) InitServiceMap() {
m.services = make(map[Type]Interface) m.services = make(map[Type]Interface)
} }
// SendAction sends action to action channel which is observed by service manager.
func (m *Manager) SendAction(action *Action) {
m.actionChannel <- action
}
// TakeAction is how service manager handles the action. // TakeAction is how service manager handles the action.
func (m *Manager) TakeAction(action *Action) { func (m *Manager) TakeAction(action *Action) {
if m.services == nil { if m.services == nil {
@ -145,8 +129,6 @@ func (m *Manager) StartServiceManager() chan *Action {
select { select {
case action := <-ch: case action := <-ch:
m.TakeAction(action) m.TakeAction(action)
case <-time.After(WaitForStatusUpdate):
utils.Logger().Info().Msg("Waiting for new action")
} }
} }
}() }()

@ -196,13 +196,22 @@ func (s *Service) DoService() {
case <-s.stopChan: case <-s.stopChan:
return return
case <-tick.C: case <-tick.C:
libp2pdis.Advertise(ctx, s.discovery, string(s.Rendezvous)) var g sync.WaitGroup
// 0 is beacon chain FIXME: use a constant g.Add(2) // 2 Advertise call
libp2pdis.Advertise(ctx, s.discovery, string(nodeconfig.NewClientGroupIDByShardID(0))) go func() {
defer g.Done()
libp2pdis.Advertise(ctx, s.discovery, string(s.Rendezvous))
}()
go func() {
defer g.Done()
// 0 is beacon chain FIXME: use a constant
libp2pdis.Advertise(ctx, s.discovery, string(nodeconfig.NewClientGroupIDByShardID(0)))
}()
g.Wait()
utils.Logger().Info(). utils.Logger().Info().
Str("Rendezvous", string(s.Rendezvous)). Str("Rendezvous", string(s.Rendezvous)).
Msg("Successfully announced!") Msg("Successfully announced!")
default: case <-time.After(findPeerInterval):
var err error var err error
s.peerInfo, err = s.discovery.FindPeers( s.peerInfo, err = s.discovery.FindPeers(
ctx, string(s.Rendezvous), coredis.Limit(discoveryLimit), ctx, string(s.Rendezvous), coredis.Limit(discoveryLimit),
@ -213,7 +222,6 @@ func (s *Service) DoService() {
} }
s.findPeers(ctx) s.findPeers(ctx)
time.Sleep(findPeerInterval)
} }
} }
} }

@ -90,6 +90,7 @@ type Consensus struct {
// whether to ignore viewID check // whether to ignore viewID check
ignoreViewIDCheck bool ignoreViewIDCheck bool
// global consensus mutex // global consensus mutex
// TODO(optimization): Avoid mutex and use more efficient locking primitives
mutex sync.Mutex mutex sync.Mutex
// consensus information update mutex // consensus information update mutex
infoMutex sync.Mutex infoMutex sync.Mutex

@ -15,10 +15,8 @@ import (
"github.com/harmony-one/harmony/internal/chain" "github.com/harmony-one/harmony/internal/chain"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/multibls" "github.com/harmony-one/harmony/multibls"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
"github.com/harmony-one/harmony/shard/committee" "github.com/harmony-one/harmony/shard/committee"
libp2p_peer "github.com/libp2p/go-libp2p-core/peer"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/rs/zerolog" "github.com/rs/zerolog"
) )
@ -68,19 +66,6 @@ func (consensus *Consensus) signAndMarshalConsensusMessage(message *msg_pb.Messa
return marshaledMessage, nil return marshaledMessage, nil
} }
// GetNodeIDs returns Node IDs of all nodes in the same shard
func (consensus *Consensus) GetNodeIDs() []libp2p_peer.ID {
nodes := []libp2p_peer.ID{consensus.host.GetID()}
consensus.validators.Range(func(k, v interface{}) bool {
if peer, ok := v.(p2p.Peer); ok {
nodes = append(nodes, peer.PeerID)
return true
}
return false
})
return nodes
}
// GetViewID returns the consensus ID // GetViewID returns the consensus ID
func (consensus *Consensus) GetViewID() uint64 { func (consensus *Consensus) GetViewID() uint64 {
return consensus.viewID return consensus.viewID
@ -135,21 +120,6 @@ func (consensus *Consensus) signConsensusMessage(message *msg_pb.Message,
return nil return nil
} }
// GetValidatorPeers returns list of validator peers.
func (consensus *Consensus) GetValidatorPeers() []p2p.Peer {
validatorPeers := []p2p.Peer{}
consensus.validators.Range(func(k, v interface{}) bool {
if peer, ok := v.(p2p.Peer); ok {
validatorPeers = append(validatorPeers, peer)
return true
}
return false
})
return validatorPeers
}
// GetViewIDSigsArray returns the signatures for viewID in viewchange // GetViewIDSigsArray returns the signatures for viewID in viewchange
func (consensus *Consensus) GetViewIDSigsArray(viewID uint64) []*bls.Sign { func (consensus *Consensus) GetViewIDSigsArray(viewID uint64) []*bls.Sign {
sigs := []*bls.Sign{} sigs := []*bls.Sign{}

@ -257,12 +257,6 @@ func (consensus *Consensus) tryCatchup() {
continue continue
} }
if consensus.BlockVerifier == nil {
// do nothing
} else if err := consensus.BlockVerifier(tmpBlock); err != nil {
consensus.getLogger().Info().Msg("[TryCatchup] block verification failed")
continue
}
committedMsg = msgs[i] committedMsg = msgs[i]
block = tmpBlock block = tmpBlock
break break
@ -334,7 +328,7 @@ func (consensus *Consensus) Start(
blockChannel chan *types.Block, stopChan, stoppedChan, startChannel chan struct{}, blockChannel chan *types.Block, stopChan, stoppedChan, startChannel chan struct{},
) { ) {
go func() { go func() {
toStart := false toStart := make(chan struct{}, 1)
isInitialLeader := consensus.IsLeader() isInitialLeader := consensus.IsLeader()
if isInitialLeader { if isInitialLeader {
consensus.getLogger().Info().Time("time", time.Now()).Msg("[ConsensusMainLoop] Waiting for consensus start") consensus.getLogger().Info().Time("time", time.Now()).Msg("[ConsensusMainLoop] Waiting for consensus start")
@ -342,7 +336,7 @@ func (consensus *Consensus) Start(
// this signal is consumed by node object to create a new block and in turn trigger a new consensus on it // this signal is consumed by node object to create a new block and in turn trigger a new consensus on it
go func() { go func() {
<-startChannel <-startChannel
toStart = true toStart <- struct{}{}
consensus.getLogger().Info().Time("time", time.Now()).Msg("[ConsensusMainLoop] Send ReadySignal") consensus.getLogger().Info().Time("time", time.Now()).Msg("[ConsensusMainLoop] Send ReadySignal")
consensus.ReadySignal <- struct{}{} consensus.ReadySignal <- struct{}{}
}() }()
@ -360,11 +354,14 @@ func (consensus *Consensus) Start(
vdfInProgress := false vdfInProgress := false
// Set up next block due time. // Set up next block due time.
consensus.NextBlockDue = time.Now().Add(consensus.BlockPeriod) consensus.NextBlockDue = time.Now().Add(consensus.BlockPeriod)
start := false
for { for {
select { select {
case <-toStart:
start = true
case <-ticker.C: case <-ticker.C:
consensus.getLogger().Debug().Msg("[ConsensusMainLoop] Ticker") consensus.getLogger().Debug().Msg("[ConsensusMainLoop] Ticker")
if !toStart && isInitialLeader { if !start && isInitialLeader {
continue continue
} }
for k, v := range consensus.consensusTimeout { for k, v := range consensus.consensusTimeout {

@ -543,6 +543,10 @@ func (consensus *Consensus) onNewView(msg *msg_pb.Message) {
return return
} }
hasBlock = true hasBlock = true
if consensus.BlockVerifier(preparedBlock); err != nil {
consensus.getLogger().Error().Err(err).Msg("[onNewView] Prepared block verification failed")
return
}
} }
if m2Mask == nil || m2Mask.Bitmap == nil || if m2Mask == nil || m2Mask.Bitmap == nil ||
@ -605,10 +609,6 @@ func (consensus *Consensus) onNewView(msg *msg_pb.Message) {
// NewView message is verified, change state to normal consensus // NewView message is verified, change state to normal consensus
if hasBlock { if hasBlock {
// Construct and send the commit message // Construct and send the commit message
if consensus.BlockVerifier(preparedBlock); err != nil {
consensus.getLogger().Error().Err(err).Msg("[onNewView] Prepared block verification failed")
return
}
commitPayload := signature.ConstructCommitPayload(consensus.ChainReader, commitPayload := signature.ConstructCommitPayload(consensus.ChainReader,
preparedBlock.Epoch(), preparedBlock.Hash(), preparedBlock.NumberU64(), preparedBlock.Header().ViewID().Uint64()) preparedBlock.Epoch(), preparedBlock.Hash(), preparedBlock.NumberU64(), preparedBlock.Header().ViewID().Uint64())
groupID := []nodeconfig.GroupID{ groupID := []nodeconfig.GroupID{

@ -283,7 +283,7 @@ func (l *txList) Forward(threshold uint64) types.PoolTransactions {
return l.txs.Forward(threshold) return l.txs.Forward(threshold)
} }
// Filter removes all transactions from the list with a cost or gas limit higher // FilterCost removes all transactions from the list with a cost or gas limit higher
// than the provided thresholds. Every removed transaction is returned for any // than the provided thresholds. Every removed transaction is returned for any
// post-removal maintenance. Strict-mode invalidated transactions are also // post-removal maintenance. Strict-mode invalidated transactions are also
// returned. // returned.
@ -292,7 +292,7 @@ func (l *txList) Forward(threshold uint64) types.PoolTransactions {
// a point in calculating all the costs or if the balance covers all. If the threshold // a point in calculating all the costs or if the balance covers all. If the threshold
// is lower than the costgas cap, the caps will be reset to a new high after removing // is lower than the costgas cap, the caps will be reset to a new high after removing
// the newly invalidated transactions. // the newly invalidated transactions.
func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.PoolTransactions, types.PoolTransactions) { func (l *txList) FilterCost(costLimit *big.Int, gasLimit uint64) (types.PoolTransactions, types.PoolTransactions) {
// If all transactions are below the threshold, short circuit // If all transactions are below the threshold, short circuit
if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit { if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
return nil, nil return nil, nil
@ -300,18 +300,26 @@ func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.PoolTransact
l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
l.gascap = gasLimit l.gascap = gasLimit
// Filter out all the transactions above the account's funds return l.Filter(func(tx types.PoolTransaction) bool {
removed := l.txs.Filter(func(tx types.PoolTransaction) bool {
cost, err := tx.Cost() cost, err := tx.Cost()
if err != nil { if err != nil {
return true // failure should lead to removal of the tx return true // failure should lead to removal of the tx
} }
return cost.Cmp(costLimit) > 0 || tx.Gas() > gasLimit return cost.Cmp(costLimit) > 0 || tx.Gas() > gasLimit
}) })
}
// Filter iterates over the list of transactions and removes all of them for which
// the specified function evaluates to true. Moreover, it returns all transactions
// that were invalidated from the filter
func (l *txList) Filter(
filter func(types.PoolTransaction) bool,
) (types.PoolTransactions, types.PoolTransactions) {
// If the list was strict, filter anything above the lowest nonce // If the list was strict, filter anything above the lowest nonce
var invalids types.PoolTransactions var invalids types.PoolTransactions
// Filter out all the transactions above the account's funds
removed := l.txs.Filter(filter)
if l.strict && len(removed) > 0 { if l.strict && len(removed) > 0 {
lowest := uint64(math.MaxUint64) lowest := uint64(math.MaxUint64)
for _, tx := range removed { for _, tx := range removed {

@ -616,7 +616,7 @@ func (pool *TxPool) Content() (map[common.Address]types.PoolTransactions, map[co
return pending, queued return pending, queued
} }
// Pending retrieves all currently processable transactions, grouped by origin // Pending retrieves all currently executable transactions, grouped by origin
// account and sorted by nonce. The returned transaction set is a copy and can be // account and sorted by nonce. The returned transaction set is a copy and can be
// freely modified by calling code. // freely modified by calling code.
func (pool *TxPool) Pending() (map[common.Address]types.PoolTransactions, error) { func (pool *TxPool) Pending() (map[common.Address]types.PoolTransactions, error) {
@ -630,6 +630,20 @@ func (pool *TxPool) Pending() (map[common.Address]types.PoolTransactions, error)
return pending, nil return pending, nil
} }
// Queued retrieves all currently non-executable transactions, grouped by origin
// account and sorted by nonce. The returned transaction set is a copy and can be
// freely modified by calling code.
func (pool *TxPool) Queued() (map[common.Address]types.PoolTransactions, error) {
pool.mu.Lock()
defer pool.mu.Unlock()
queued := make(map[common.Address]types.PoolTransactions)
for addr, list := range pool.queue {
queued[addr] = list.Flatten()
}
return queued, nil
}
// Locals retrieves the accounts currently considered local by the pool. // Locals retrieves the accounts currently considered local by the pool.
func (pool *TxPool) Locals() []common.Address { func (pool *TxPool) Locals() []common.Address {
pool.mu.Lock() pool.mu.Lock()
@ -1262,7 +1276,7 @@ func (pool *TxPool) promoteExecutables(accounts []common.Address) {
// Do not report to error sink as old txs are on chain or meaningful error caught elsewhere. // Do not report to error sink as old txs are on chain or meaningful error caught elsewhere.
} }
// Drop all transactions that are too costly (low balance or out of gas) // Drop all transactions that are too costly (low balance or out of gas)
drops, _ := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas) drops, _ := list.FilterCost(pool.currentState.GetBalance(addr), pool.currentMaxGas)
for _, tx := range drops { for _, tx := range drops {
hash := tx.Hash() hash := tx.Hash()
pool.all.Remove(hash) pool.all.Remove(hash)
@ -1435,14 +1449,25 @@ func (pool *TxPool) demoteUnexecutables() {
// Do not report to error sink as old txs are on chain or meaningful error caught elsewhere. // Do not report to error sink as old txs are on chain or meaningful error caught elsewhere.
} }
// Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later
drops, invalids := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas) drops, invalids := list.FilterCost(pool.currentState.GetBalance(addr), pool.currentMaxGas)
// Drop all staking transactions that are now invalid, queue any invalids back for later
stakingDrops, stakingInvalids := list.Filter(func(tx types.PoolTransaction) bool {
if _, ok := tx.(*staking.StakingTransaction); !ok {
// Do not remove anything other than staking transactions
return false
}
err := pool.validateTx(tx, false)
return err != nil
})
drops = append(drops, stakingDrops...)
invalids = append(invalids, stakingInvalids...)
for _, tx := range drops { for _, tx := range drops {
hash := tx.Hash() hash := tx.Hash()
pool.all.Remove(hash) pool.all.Remove(hash)
pool.priced.Removed() pool.priced.Removed()
pendingNofundsCounter.Inc(1) pendingNofundsCounter.Inc(1)
pool.txErrorSink.Add(tx, fmt.Errorf("removed unpayable pending transaction")) pool.txErrorSink.Add(tx, fmt.Errorf("removed unexecutable pending transaction"))
logger.Warn().Str("hash", hash.Hex()).Msg("Removed unpayable pending transaction") logger.Warn().Str("hash", hash.Hex()).Msg("Removed unexecutable pending transaction")
} }
for _, tx := range invalids { for _, tx := range invalids {
hash := tx.Hash() hash := tx.Hash()
@ -1451,7 +1476,7 @@ func (pool *TxPool) demoteUnexecutables() {
pool.txErrorSink.Add(tx, err) pool.txErrorSink.Add(tx, err)
} }
} }
// If there's a gap in front, alert (should never happen) and postpone all transactions // If there's a gap in front, alert (should never happen)
if list.Len() > 0 && list.txs.Get(nonce) == nil { if list.Len() > 0 && list.txs.Get(nonce) == nil {
for _, tx := range list.Cap(0) { for _, tx := range list.Cap(0) {
hash := tx.Hash() hash := tx.Hash()

@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/api/proto" "github.com/harmony-one/harmony/api/proto"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/consensus/quorum" "github.com/harmony-one/harmony/consensus/quorum"
@ -20,6 +21,7 @@ import (
"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"
internal_bls "github.com/harmony-one/harmony/crypto/bls"
internal_common "github.com/harmony-one/harmony/internal/common" internal_common "github.com/harmony-one/harmony/internal/common"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node" nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common" commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common"
@ -243,10 +245,17 @@ func (b *APIBackend) GetPoolTransactions() (types.PoolTransactions, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
queued, err := b.hmy.txPool.Queued()
if err != nil {
return nil, err
}
var txs types.PoolTransactions var txs types.PoolTransactions
for _, batch := range pending { for _, batch := range pending {
txs = append(txs, batch...) txs = append(txs, batch...)
} }
for _, batch := range queued {
txs = append(txs, batch...)
}
return txs, nil return txs, nil
} }
@ -848,3 +857,33 @@ func (b *APIBackend) GetNodeMetadata() commonRPC.NodeMetadata {
c, c,
} }
} }
// GetBlockSigners ..
func (b *APIBackend) GetBlockSigners(ctx context.Context, blockNr rpc.BlockNumber) (shard.SlotList, *internal_bls.Mask, error) {
block, err := b.BlockByNumber(ctx, blockNr)
if err != nil {
return nil, nil, err
}
blockWithSigners, err := b.BlockByNumber(ctx, blockNr+1)
if err != nil {
return nil, nil, err
}
committee, err := b.GetValidators(block.Epoch())
if err != nil {
return nil, nil, err
}
pubkeys := make([]*bls.PublicKey, len(committee.Slots))
for i, validator := range committee.Slots {
pubkeys[i] = new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(pubkeys[i])
}
mask, err := internal_bls.NewMask(pubkeys, nil)
if err != nil {
return nil, nil, err
}
err = mask.SetMask(blockWithSigners.Header().LastCommitBitmap())
if err != nil {
return nil, nil, err
}
return committee.Slots, mask, nil
}

@ -14,6 +14,7 @@ import (
"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/crypto/bls"
commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common" commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
@ -91,4 +92,5 @@ type Backend interface {
GetLastCrossLinks() ([]*types.CrossLink, error) GetLastCrossLinks() ([]*types.CrossLink, error)
GetLatestChainHeaders() *block.HeaderPair GetLatestChainHeaders() *block.HeaderPair
GetNodeMetadata() commonRPC.NodeMetadata GetNodeMetadata() commonRPC.NodeMetadata
GetBlockSigners(ctx context.Context, blockNr rpc.BlockNumber) (shard.SlotList, *bls.Mask, error)
} }

@ -18,7 +18,6 @@ import (
"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/vm" "github.com/harmony-one/harmony/core/vm"
internal_bls "github.com/harmony-one/harmony/crypto/bls"
internal_common "github.com/harmony-one/harmony/internal/common" internal_common "github.com/harmony-one/harmony/internal/common"
"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"
@ -183,9 +182,6 @@ func (s *PublicBlockChainAPI) GetBlocks(ctx context.Context, blockStart rpc.Bloc
// GetValidators returns validators list for a particular epoch. // GetValidators returns validators list for a particular epoch.
func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (map[string]interface{}, error) { func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (map[string]interface{}, error) {
if err := s.isBeaconShard(); err != nil {
return nil, err
}
committee, err := s.b.GetValidators(big.NewInt(epoch)) committee, err := s.b.GetValidators(big.NewInt(epoch))
if err != nil { if err != nil {
return nil, err return nil, err
@ -217,6 +213,20 @@ func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (m
return result, nil return result, nil
} }
// GetValidatorKeys returns list of bls public keys in the committee for a particular epoch.
func (s *PublicBlockChainAPI) GetValidatorKeys(ctx context.Context, epoch int64) ([]string, error) {
committee, err := s.b.GetValidators(big.NewInt(epoch))
if err != nil {
return nil, err
}
validators := make([]string, len(committee.Slots))
for i, v := range committee.Slots {
validators[i] = v.BLSPublicKey.Hex()
}
return validators, nil
}
// IsLastBlock checks if block is last epoch block. // IsLastBlock checks if block is last epoch block.
func (s *PublicBlockChainAPI) IsLastBlock(blockNum uint64) (bool, error) { func (s *PublicBlockChainAPI) IsLastBlock(blockNum uint64) (bool, error) {
if err := s.isBeaconShard(); err != nil { if err := s.isBeaconShard(); err != nil {
@ -241,44 +251,46 @@ func (s *PublicBlockChainAPI) GetBlockSigners(ctx context.Context, blockNr rpc.B
if err := s.isBlockGreaterThanLatest(blockNr); err != nil { if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
return nil, err return nil, err
} }
block, err := s.b.BlockByNumber(ctx, blockNr) slots, mask, err := s.b.GetBlockSigners(ctx, blockNr)
if err != nil {
return nil, err
}
blockWithSigners, err := s.b.BlockByNumber(ctx, blockNr+1)
if err != nil { if err != nil {
return nil, err return nil, err
} }
committee, err := s.b.GetValidators(block.Epoch()) signers := []string{}
if err != nil { for _, validator := range slots {
return nil, err oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil {
return nil, err
}
blsPublicKey := new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(blsPublicKey)
if ok, err := mask.KeyEnabled(blsPublicKey); err == nil && ok {
signers = append(signers, oneAddress)
}
} }
pubkeys := make([]*bls.PublicKey, len(committee.Slots)) return signers, nil
for i, validator := range committee.Slots { }
pubkeys[i] = new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(pubkeys[i]) // GetBlockSignerKeys returns bls public keys that signed the block.
func (s *PublicBlockChainAPI) GetBlockSignerKeys(ctx context.Context, blockNr rpc.BlockNumber) ([]string, error) {
if uint64(blockNr) == 0 {
return []string{}, nil
} }
mask, err := internal_bls.NewMask(pubkeys, nil) if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
if err != nil {
return nil, err return nil, err
} }
err = mask.SetMask(blockWithSigners.Header().LastCommitBitmap()) slots, mask, err := s.b.GetBlockSigners(ctx, blockNr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
result := []string{} signers := []string{}
for _, validator := range committee.Slots { for _, validator := range slots {
oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil {
return nil, err
}
blsPublicKey := new(bls.PublicKey) blsPublicKey := new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(blsPublicKey) validator.BLSPublicKey.ToLibBLSPublicKey(blsPublicKey)
if ok, err := mask.KeyEnabled(blsPublicKey); err == nil && ok { if ok, err := mask.KeyEnabled(blsPublicKey); err == nil && ok {
result = append(result, oneAddress) signers = append(signers, validator.BLSPublicKey.Hex())
} }
} }
return result, nil return signers, nil
} }
// IsBlockSigner returns true if validator with address signed blockNr block. // IsBlockSigner returns true if validator with address signed blockNr block.
@ -289,32 +301,11 @@ func (s *PublicBlockChainAPI) IsBlockSigner(ctx context.Context, blockNr rpc.Blo
if err := s.isBlockGreaterThanLatest(blockNr); err != nil { if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
return false, err return false, err
} }
block, err := s.b.BlockByNumber(ctx, blockNr) slots, mask, err := s.b.GetBlockSigners(ctx, blockNr)
if err != nil {
return false, err
}
blockWithSigners, err := s.b.BlockByNumber(ctx, blockNr+1)
if err != nil { if err != nil {
return false, err return false, err
} }
committee, err := s.b.GetValidators(block.Epoch()) for _, validator := range slots {
if err != nil {
return false, err
}
pubkeys := make([]*bls.PublicKey, len(committee.Slots))
for i, validator := range committee.Slots {
pubkeys[i] = new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(pubkeys[i])
}
mask, err := internal_bls.NewMask(pubkeys, nil)
if err != nil {
return false, err
}
err = mask.SetMask(blockWithSigners.Header().LastCommitBitmap())
if err != nil {
return false, err
}
for _, validator := range committee.Slots {
oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress) oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil { if err != nil {
return false, err return false, err
@ -683,17 +674,16 @@ func (s *PublicBlockChainAPI) getAllValidatorInformation(
validatorsNum = len(addresses) - start validatorsNum = len(addresses) - start
} }
} }
validators := make([]*staking.ValidatorRPCEnhanced, validatorsNum) validators := []*staking.ValidatorRPCEnhanced{}
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr)) block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr))
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "could not retrieve the block information for block number: %d", blockNr) return nil, errors.Wrapf(err, "could not retrieve the block information for block number: %d", blockNr)
} }
for i := start; i < start+validatorsNum; i++ { for i := start; i < start+validatorsNum; i++ {
information, err := s.b.GetValidatorInformation(addresses[i], block) information, err := s.b.GetValidatorInformation(addresses[i], block)
if err != nil { if err == nil {
return nil, err validators = append(validators, information)
} }
validators[i-start] = information
} }
return validators, nil return validators, nil
} }

@ -6,7 +6,7 @@ import (
"strings" "strings"
"time" "time"
types2 "github.com/harmony-one/harmony/staking/types" staking "github.com/harmony-one/harmony/staking/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@ -208,7 +208,7 @@ func newRPCTransaction(
// newRPCStakingTransaction returns a staking transaction that will serialize to the RPC // newRPCStakingTransaction returns a staking transaction that will serialize to the RPC
// representation, with the given location metadata set (if available). // representation, with the given location metadata set (if available).
func newRPCStakingTransaction(tx *types2.StakingTransaction, blockHash common.Hash, func newRPCStakingTransaction(tx *staking.StakingTransaction, blockHash common.Hash,
blockNumber uint64, timestamp uint64, index uint64, blockNumber uint64, timestamp uint64, index uint64,
) *RPCStakingTransaction { ) *RPCStakingTransaction {
from, err := tx.SenderAddress() from, err := tx.SenderAddress()
@ -217,13 +217,15 @@ func newRPCStakingTransaction(tx *types2.StakingTransaction, blockHash common.Ha
} }
v, r, s := tx.RawSignatureValues() v, r, s := tx.RawSignatureValues()
stakingTxType := tx.StakingType()
message := tx.StakingMessage()
fields := map[string]interface{}{} fields := map[string]interface{}{}
switch stakingTxType { switch tx.StakingType() {
case types2.DirectiveCreateValidator: case staking.DirectiveCreateValidator:
msg, ok := message.(types2.CreateValidator) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveCreateValidator)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.CreateValidator)
if !ok { if !ok {
return nil return nil
} }
@ -246,8 +248,12 @@ func newRPCStakingTransaction(tx *types2.StakingTransaction, blockHash common.Ha
"details": msg.Description.Details, "details": msg.Description.Details,
"slotPubKeys": msg.SlotPubKeys, "slotPubKeys": msg.SlotPubKeys,
} }
case types2.DirectiveEditValidator: case staking.DirectiveEditValidator:
msg, ok := message.(types2.EditValidator) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveEditValidator)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.EditValidator)
if !ok { if !ok {
return nil return nil
} }
@ -273,8 +279,12 @@ func newRPCStakingTransaction(tx *types2.StakingTransaction, blockHash common.Ha
"slotPubKeyToAdd": msg.SlotKeyToAdd, "slotPubKeyToAdd": msg.SlotKeyToAdd,
"slotPubKeyToRemove": msg.SlotKeyToRemove, "slotPubKeyToRemove": msg.SlotKeyToRemove,
} }
case types2.DirectiveCollectRewards: case staking.DirectiveCollectRewards:
msg, ok := message.(types2.CollectRewards) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveCollectRewards)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.CollectRewards)
if !ok { if !ok {
return nil return nil
} }
@ -285,8 +295,12 @@ func newRPCStakingTransaction(tx *types2.StakingTransaction, blockHash common.Ha
fields = map[string]interface{}{ fields = map[string]interface{}{
"delegatorAddress": delegatorAddress, "delegatorAddress": delegatorAddress,
} }
case types2.DirectiveDelegate: case staking.DirectiveDelegate:
msg, ok := message.(types2.Delegate) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveDelegate)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.Delegate)
if !ok { if !ok {
return nil return nil
} }
@ -303,8 +317,12 @@ func newRPCStakingTransaction(tx *types2.StakingTransaction, blockHash common.Ha
"validatorAddress": validatorAddress, "validatorAddress": validatorAddress,
"amount": (*hexutil.Big)(msg.Amount), "amount": (*hexutil.Big)(msg.Amount),
} }
case types2.DirectiveUndelegate: case staking.DirectiveUndelegate:
msg, ok := message.(types2.Undelegate) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveUndelegate)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.Undelegate)
if !ok { if !ok {
return nil return nil
} }
@ -332,7 +350,7 @@ func newRPCStakingTransaction(tx *types2.StakingTransaction, blockHash common.Ha
V: (*hexutil.Big)(v), V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r), R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s), S: (*hexutil.Big)(s),
Type: stakingTxType.String(), Type: tx.StakingType().String(),
Msg: fields, Msg: fields,
} }
if blockHash != (common.Hash{}) { if blockHash != (common.Hash{}) {
@ -423,11 +441,11 @@ func RPCMarshalBlock(b *types.Block, blockArgs BlockArgs) (map[string]interface{
fields["transactions"] = transactions fields["transactions"] = transactions
if blockArgs.InclStaking { if blockArgs.InclStaking {
formatStakingTx := func(tx *types2.StakingTransaction) (interface{}, error) { formatStakingTx := func(tx *staking.StakingTransaction) (interface{}, error) {
return tx.Hash(), nil return tx.Hash(), nil
} }
if blockArgs.FullTx { if blockArgs.FullTx {
formatStakingTx = func(tx *types2.StakingTransaction) (interface{}, error) { formatStakingTx = func(tx *staking.StakingTransaction) (interface{}, error) {
return newRPCStakingTransactionFromBlockHash(b, tx.Hash()), nil return newRPCStakingTransactionFromBlockHash(b, tx.Hash()), nil
} }
} }

@ -14,6 +14,7 @@ import (
"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/crypto/bls"
commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common" commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
@ -87,4 +88,5 @@ type Backend interface {
GetLastCrossLinks() ([]*types.CrossLink, error) GetLastCrossLinks() ([]*types.CrossLink, error)
GetLatestChainHeaders() *block.HeaderPair GetLatestChainHeaders() *block.HeaderPair
GetNodeMetadata() commonRPC.NodeMetadata GetNodeMetadata() commonRPC.NodeMetadata
GetBlockSigners(ctx context.Context, blockNr rpc.BlockNumber) (shard.SlotList, *bls.Mask, error)
} }

@ -17,7 +17,6 @@ import (
"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/vm" "github.com/harmony-one/harmony/core/vm"
internal_bls "github.com/harmony-one/harmony/crypto/bls"
internal_common "github.com/harmony-one/harmony/internal/common" internal_common "github.com/harmony-one/harmony/internal/common"
"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"
@ -144,9 +143,6 @@ func (s *PublicBlockChainAPI) GetBlocks(ctx context.Context, blockStart, blockEn
// GetValidators returns validators list for a particular epoch. // GetValidators returns validators list for a particular epoch.
func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (map[string]interface{}, error) { func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (map[string]interface{}, error) {
if err := s.isBeaconShard(); err != nil {
return nil, err
}
committee, err := s.b.GetValidators(big.NewInt(epoch)) committee, err := s.b.GetValidators(big.NewInt(epoch))
if err != nil { if err != nil {
return nil, err return nil, err
@ -179,6 +175,20 @@ func (s *PublicBlockChainAPI) GetValidators(ctx context.Context, epoch int64) (m
return result, nil return result, nil
} }
// GetValidatorKeys returns list of bls public keys in the committee for a particular epoch.
func (s *PublicBlockChainAPI) GetValidatorKeys(ctx context.Context, epoch int64) ([]string, error) {
committee, err := s.b.GetValidators(big.NewInt(epoch))
if err != nil {
return nil, err
}
validators := make([]string, len(committee.Slots))
for i, v := range committee.Slots {
validators[i] = v.BLSPublicKey.Hex()
}
return validators, nil
}
// IsLastBlock checks if block is last epoch block. // IsLastBlock checks if block is last epoch block.
func (s *PublicBlockChainAPI) IsLastBlock(blockNum uint64) (bool, error) { func (s *PublicBlockChainAPI) IsLastBlock(blockNum uint64) (bool, error) {
if err := s.isBeaconShard(); err != nil { if err := s.isBeaconShard(); err != nil {
@ -203,44 +213,46 @@ func (s *PublicBlockChainAPI) GetBlockSigners(ctx context.Context, blockNr uint6
if err := s.isBlockGreaterThanLatest(blockNr); err != nil { if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
return nil, err return nil, err
} }
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr)) slots, mask, err := s.b.GetBlockSigners(ctx, rpc.BlockNumber(blockNr))
if err != nil {
return nil, err
}
blockWithSigners, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr+1))
if err != nil { if err != nil {
return nil, err return nil, err
} }
committee, err := s.b.GetValidators(block.Epoch()) signers := []string{}
if err != nil { for _, validator := range slots {
return nil, err oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil {
return nil, err
}
blsPublicKey := new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(blsPublicKey)
if ok, err := mask.KeyEnabled(blsPublicKey); err == nil && ok {
signers = append(signers, oneAddress)
}
} }
pubkeys := make([]*bls.PublicKey, len(committee.Slots)) return signers, nil
for i, validator := range committee.Slots { }
pubkeys[i] = new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(pubkeys[i]) // GetBlockSignerKeys returns bls public keys that signed the block.
func (s *PublicBlockChainAPI) GetBlockSignerKeys(ctx context.Context, blockNr uint64) ([]string, error) {
if blockNr == 0 || blockNr >= uint64(s.BlockNumber()) {
return []string{}, nil
} }
mask, err := internal_bls.NewMask(pubkeys, nil) if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
if err != nil {
return nil, err return nil, err
} }
err = mask.SetMask(blockWithSigners.Header().LastCommitBitmap()) slots, mask, err := s.b.GetBlockSigners(ctx, rpc.BlockNumber(blockNr))
if err != nil { if err != nil {
return nil, err return nil, err
} }
result := []string{} signers := []string{}
for _, validator := range committee.Slots { for _, validator := range slots {
oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil {
return nil, err
}
blsPublicKey := new(bls.PublicKey) blsPublicKey := new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(blsPublicKey) validator.BLSPublicKey.ToLibBLSPublicKey(blsPublicKey)
if ok, err := mask.KeyEnabled(blsPublicKey); err == nil && ok { if ok, err := mask.KeyEnabled(blsPublicKey); err == nil && ok {
result = append(result, oneAddress) signers = append(signers, validator.BLSPublicKey.Hex())
} }
} }
return result, nil return signers, nil
} }
// IsBlockSigner returns true if validator with address signed blockNr block. // IsBlockSigner returns true if validator with address signed blockNr block.
@ -251,32 +263,11 @@ func (s *PublicBlockChainAPI) IsBlockSigner(ctx context.Context, blockNr uint64,
if err := s.isBlockGreaterThanLatest(blockNr); err != nil { if err := s.isBlockGreaterThanLatest(blockNr); err != nil {
return false, err return false, err
} }
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr)) slots, mask, err := s.b.GetBlockSigners(ctx, rpc.BlockNumber(blockNr))
if err != nil {
return false, err
}
blockWithSigners, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr+1))
if err != nil { if err != nil {
return false, err return false, err
} }
committee, err := s.b.GetValidators(block.Epoch()) for _, validator := range slots {
if err != nil {
return false, err
}
pubkeys := make([]*bls.PublicKey, len(committee.Slots))
for i, validator := range committee.Slots {
pubkeys[i] = new(bls.PublicKey)
validator.BLSPublicKey.ToLibBLSPublicKey(pubkeys[i])
}
mask, err := internal_bls.NewMask(pubkeys, nil)
if err != nil {
return false, err
}
err = mask.SetMask(blockWithSigners.Header().LastCommitBitmap())
if err != nil {
return false, err
}
for _, validator := range committee.Slots {
oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress) oneAddress, err := internal_common.AddressToBech32(validator.EcdsaAddress)
if err != nil { if err != nil {
return false, err return false, err
@ -629,17 +620,16 @@ func (s *PublicBlockChainAPI) getAllValidatorInformation(
validatorsNum = len(addresses) - start validatorsNum = len(addresses) - start
} }
} }
validators := make([]*staking.ValidatorRPCEnhanced, validatorsNum) validators := []*staking.ValidatorRPCEnhanced{}
block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr)) block, err := s.b.BlockByNumber(ctx, rpc.BlockNumber(blockNr))
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "could not retrieve the block information for block number: %d", blockNr) return nil, errors.Wrapf(err, "could not retrieve the block information for block number: %d", blockNr)
} }
for i := start; i < start+validatorsNum; i++ { for i := start; i < start+validatorsNum; i++ {
information, err := s.b.GetValidatorInformation(addresses[i], block) information, err := s.b.GetValidatorInformation(addresses[i], block)
if err != nil { if err == nil {
return nil, err validators = append(validators, information)
} }
validators[i-start] = information
} }
return validators, nil return validators, nil
} }

@ -6,7 +6,7 @@ import (
"strings" "strings"
"time" "time"
types2 "github.com/harmony-one/harmony/staking/types" staking "github.com/harmony-one/harmony/staking/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@ -210,7 +210,7 @@ func newRPCTransaction(
// newRPCStakingTransaction returns a staking transaction that will serialize to the RPC // newRPCStakingTransaction returns a staking transaction that will serialize to the RPC
// representation, with the given location metadata set (if available). // representation, with the given location metadata set (if available).
func newRPCStakingTransaction( func newRPCStakingTransaction(
tx *types2.StakingTransaction, blockHash common.Hash, tx *staking.StakingTransaction, blockHash common.Hash,
blockNumber uint64, timestamp uint64, index uint64, blockNumber uint64, timestamp uint64, index uint64,
) *RPCStakingTransaction { ) *RPCStakingTransaction {
from, err := tx.SenderAddress() from, err := tx.SenderAddress()
@ -219,13 +219,15 @@ func newRPCStakingTransaction(
} }
v, r, s := tx.RawSignatureValues() v, r, s := tx.RawSignatureValues()
stakingTxType := tx.StakingType()
message := tx.StakingMessage()
fields := make(map[string]interface{}) fields := make(map[string]interface{})
switch stakingTxType { switch tx.StakingType() {
case types2.DirectiveCreateValidator: case staking.DirectiveCreateValidator:
msg, ok := message.(types2.CreateValidator) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveCreateValidator)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.CreateValidator)
if !ok { if !ok {
return nil return nil
} }
@ -248,8 +250,12 @@ func newRPCStakingTransaction(
"details": msg.Description.Details, "details": msg.Description.Details,
"slotPubKeys": msg.SlotPubKeys, "slotPubKeys": msg.SlotPubKeys,
} }
case types2.DirectiveEditValidator: case staking.DirectiveEditValidator:
msg, ok := message.(types2.EditValidator) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveEditValidator)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.EditValidator)
if !ok { if !ok {
return nil return nil
} }
@ -275,8 +281,12 @@ func newRPCStakingTransaction(
"slotPubKeyToAdd": msg.SlotKeyToAdd, "slotPubKeyToAdd": msg.SlotKeyToAdd,
"slotPubKeyToRemove": msg.SlotKeyToRemove, "slotPubKeyToRemove": msg.SlotKeyToRemove,
} }
case types2.DirectiveCollectRewards: case staking.DirectiveCollectRewards:
msg, ok := message.(types2.CollectRewards) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveCollectRewards)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.CollectRewards)
if !ok { if !ok {
return nil return nil
} }
@ -287,8 +297,12 @@ func newRPCStakingTransaction(
fields = map[string]interface{}{ fields = map[string]interface{}{
"delegatorAddress": delegatorAddress, "delegatorAddress": delegatorAddress,
} }
case types2.DirectiveDelegate: case staking.DirectiveDelegate:
msg, ok := message.(types2.Delegate) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveDelegate)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.Delegate)
if !ok { if !ok {
return nil return nil
} }
@ -305,8 +319,12 @@ func newRPCStakingTransaction(
"validatorAddress": validatorAddress, "validatorAddress": validatorAddress,
"amount": msg.Amount, "amount": msg.Amount,
} }
case types2.DirectiveUndelegate: case staking.DirectiveUndelegate:
msg, ok := message.(types2.Undelegate) rawMsg, err := staking.RLPDecodeStakeMsg(tx.Data(), staking.DirectiveUndelegate)
if err != nil {
return nil
}
msg, ok := rawMsg.(*staking.Undelegate)
if !ok { if !ok {
return nil return nil
} }
@ -334,12 +352,12 @@ func newRPCStakingTransaction(
V: (*hexutil.Big)(v), V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r), R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s), S: (*hexutil.Big)(s),
Type: stakingTxType.String(), Type: tx.StakingType().String(),
Msg: fields, Msg: fields,
} }
if blockHash != (common.Hash{}) { if blockHash != (common.Hash{}) {
result.BlockHash = blockHash result.BlockHash = blockHash
result.BlockNumber = (*big.Int)(new(big.Int).SetUint64(blockNumber)) result.BlockNumber = new(big.Int).SetUint64(blockNumber)
result.TransactionIndex = index result.TransactionIndex = index
} }
@ -425,11 +443,11 @@ func RPCMarshalBlock(b *types.Block, blockArgs BlockArgs) (map[string]interface{
fields["transactions"] = transactions fields["transactions"] = transactions
if blockArgs.InclStaking { if blockArgs.InclStaking {
formatStakingTx := func(tx *types2.StakingTransaction) (interface{}, error) { formatStakingTx := func(tx *staking.StakingTransaction) (interface{}, error) {
return tx.Hash(), nil return tx.Hash(), nil
} }
if blockArgs.FullTx { if blockArgs.FullTx {
formatStakingTx = func(tx *types2.StakingTransaction) (interface{}, error) { formatStakingTx = func(tx *staking.StakingTransaction) (interface{}, error) {
return newRPCStakingTransactionFromBlockHash(b, tx.Hash()), nil return newRPCStakingTransactionFromBlockHash(b, tx.Hash()), nil
} }
} }

@ -14,6 +14,7 @@ import (
"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/crypto/bls"
"github.com/harmony-one/harmony/internal/hmyapi/apiv1" "github.com/harmony-one/harmony/internal/hmyapi/apiv1"
"github.com/harmony-one/harmony/internal/hmyapi/apiv2" "github.com/harmony-one/harmony/internal/hmyapi/apiv2"
commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common" commonRPC "github.com/harmony-one/harmony/internal/hmyapi/common"
@ -81,6 +82,7 @@ type Backend interface {
GetLastCrossLinks() ([]*types.CrossLink, error) GetLastCrossLinks() ([]*types.CrossLink, error)
GetLatestChainHeaders() *block.HeaderPair GetLatestChainHeaders() *block.HeaderPair
GetNodeMetadata() commonRPC.NodeMetadata GetNodeMetadata() commonRPC.NodeMetadata
GetBlockSigners(ctx context.Context, blockNr rpc.BlockNumber) (shard.SlotList, *bls.Mask, error)
} }
// GetAPIs returns all the APIs. // GetAPIs returns all the APIs.

@ -138,8 +138,6 @@ type Node struct {
ContractDeployerKey *ecdsa.PrivateKey ContractDeployerKey *ecdsa.PrivateKey
ContractDeployerCurrentNonce uint64 // The nonce of the deployer contract at current block ContractDeployerCurrentNonce uint64 // The nonce of the deployer contract at current block
ContractAddresses []common.Address ContractAddresses []common.Address
// Duplicated Ping Message Received
duplicatedPing sync.Map
// Channel to notify consensus service to really start consensus // Channel to notify consensus service to really start consensus
startConsensus chan struct{} startConsensus chan struct{}
// node configuration, including group ID, shard ID, etc // node configuration, including group ID, shard ID, etc

@ -530,7 +530,7 @@ any_new_binaries() {
fi fi
fi fi
curl -sSf http://${BUCKET}.s3.amazonaws.com/${FOLDER}/md5sum.txt -o "${outdir}/md5sum.txt.new" || return $? curl -sSf http://${BUCKET}.s3.amazonaws.com/${FOLDER}/md5sum.txt -o "${outdir}/md5sum.txt.new" || return $?
if diff $outdir/md5sum.txt.new md5sum.txt if diff "${outdir}/md5sum.txt.new" "${outdir}/md5sum.txt"
then then
rm "${outdir}/md5sum.txt.new" rm "${outdir}/md5sum.txt.new"
else else

@ -62,7 +62,7 @@ var (
errDuplicateSlotKeys = errors.New("slot keys can not have duplicates") errDuplicateSlotKeys = errors.New("slot keys can not have duplicates")
// ErrExcessiveBLSKeys .. // ErrExcessiveBLSKeys ..
ErrExcessiveBLSKeys = errors.New("more slot keys provided than allowed") ErrExcessiveBLSKeys = errors.New("more slot keys provided than allowed")
errCannotChangeBannedTaint = errors.New("cannot change validator banned status") errCannotChangeBannedTrait = errors.New("cannot change validator banned status")
) )
// ValidatorSnapshotReader .. // ValidatorSnapshotReader ..
@ -645,7 +645,7 @@ func UpdateValidatorFromEditMsg(validator *Validator, edit *EditValidator, epoch
switch validator.Status { switch validator.Status {
case effective.Banned: case effective.Banned:
return errCannotChangeBannedTaint return errCannotChangeBannedTrait
default: default:
switch edit.EPOSStatus { switch edit.EPOSStatus {
case effective.Active, effective.Inactive: case effective.Active, effective.Inactive:

@ -1,3 +1,4 @@
./test/kill_node.sh ./test/kill_node.sh
rm -rf tmp_log* rm -rf tmp_log*
rm *.rlp
./test/deploy.sh -D 60000 ./test/configs/local-resharding.txt ./test/deploy.sh -D 60000 ./test/configs/local-resharding.txt

@ -15,6 +15,7 @@ USER=$(whoami)
set -eo pipefail set -eo pipefail
export GO111MODULE=on export GO111MODULE=on
OS=$(uname -s)
mkdir -p .hmy mkdir -p .hmy
if [ -f ".hmy/blspass.txt" ] if [ -f ".hmy/blspass.txt" ]
@ -77,6 +78,7 @@ USAGE: $ME [OPTIONS] config_file_name [extra args to node]
-n dryrun mode (default: $DRYRUN) -n dryrun mode (default: $DRYRUN)
-N network network type (default: $NETWORK) -N network network type (default: $NETWORK)
-B don't build the binary -B don't build the binary
-v verbosity in log (default: $VERBOSE)
This script will build all the binaries and start harmony and based on the configuration file. This script will build all the binaries and start harmony and based on the configuration file.
@ -95,6 +97,7 @@ SHARDS=2
DRYRUN= DRYRUN=
SYNC=true SYNC=true
NETWORK=localnet NETWORK=localnet
VERBOSE=false
while getopts "hD:m:s:nBN:" option; do while getopts "hD:m:s:nBN:" option; do
case $option in case $option in
@ -105,6 +108,7 @@ while getopts "hD:m:s:nBN:" option; do
n) DRYRUN=echo ;; n) DRYRUN=echo ;;
B) NOBUILD=true ;; B) NOBUILD=true ;;
N) NETWORK=$OPTARG ;; N) NETWORK=$OPTARG ;;
v) VERBOSE=true ;;
esac esac
done done
@ -126,7 +130,13 @@ cleanup
# Also it's recommended to use `go build` for testing the whole exe. # Also it's recommended to use `go build` for testing the whole exe.
if [ "${NOBUILD}" != "true" ]; then if [ "${NOBUILD}" != "true" ]; then
pushd $ROOT pushd $ROOT
scripts/go_executable_build.sh -S if [ "$OS" = "Darwin" ]; then
# MacOS doesn't support static build
scripts/go_executable_build.sh -S
else
# Static build on Linux platform
scripts/go_executable_build.sh -s
fi
popd popd
fi fi
@ -145,7 +155,14 @@ echo "bootnode launched." + " $BN_MA"
unset -v base_args unset -v base_args
declare -a base_args args declare -a base_args args
base_args=(-log_folder "${log_folder}" -min_peers "${MIN}" -bootnodes "${BN_MA}" -network_type="$NETWORK" -blspass file:.hmy/blspass.txt -dns=false)
if $VERBOSE; then
verbosity=5
else
verbosity=3
fi
base_args=(-log_folder "${log_folder}" -min_peers "${MIN}" -bootnodes "${BN_MA}" -network_type="$NETWORK" -blspass file:.hmy/blspass.txt -dns=false -verbosity="${verbosity}")
sleep 2 sleep 2
# Start nodes # Start nodes

Loading…
Cancel
Save