Merge pull request #1706 from rlan35/mainnet_release_1005_merge_s3

Mainnet release 1005 merge s3
pull/1726/head
Rongjian Lan 5 years ago committed by GitHub
commit cbb2d4997f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      accounts/keystore/keystore.go
  2. 39
      api/service/config.go
  3. 26
      api/service/discovery/service.go
  4. 17
      api/service/explorer/service.go
  5. 8
      api/service/explorer/storage.go
  6. 21
      api/service/explorer/structs.go
  7. 5
      api/service/manager_test.go
  8. 15
      api/service/networkinfo/service.go
  9. 3
      api/service/networkinfo/service_test.go
  10. 10
      cmd/client/txgen/main.go
  11. 4
      cmd/client/wallet/main.go
  12. 4
      cmd/client/wallet_stress_test/main.go
  13. 34
      cmd/harmony/main.go
  14. 24
      cmd/staking/main.go
  15. 173
      cmd/staking/root.go
  16. 7
      consensus/consensus_msg_sender.go
  17. 16
      consensus/consensus_v2.go
  18. 11
      consensus/view_change.go
  19. 7
      core/error.go
  20. 4
      drand/drand_leader.go
  21. 4
      drand/drand_validator.go
  22. 1
      go.mod
  23. 9
      hmy/api_backend.go
  24. 2
      hmy/backend.go
  25. 36
      internal/configs/node/config.go
  26. 8
      internal/configs/node/config_test.go
  27. 55
      internal/configs/node/group.go
  28. 2
      internal/configs/node/group_test.go
  29. 3
      internal/hmyapi/backend.go
  30. 2
      internal/hmyapi/blockchain.go
  31. 72
      internal/hmyapi/transactionpool.go
  32. 34
      internal/hmyapi/types.go
  33. 38
      internal/hmyapi/util.go
  34. 42
      node/node.go
  35. 6
      node/node_cross_shard.go
  36. 15
      node/node_handler.go
  37. 1
      node/node_newblock.go
  38. 4
      node/node_resharding.go
  39. 7
      node/service_setup.go
  40. 28
      node/worker/worker.go
  41. 10
      node/worker/worker_test.go
  42. 5
      p2p/host.go
  43. 5
      p2p/host/hostv2/hostv2.go
  44. 6
      p2p/host/hostv2/hostv2_test.go
  45. 5
      p2p/host/mock/host_mock.go
  46. 11
      p2p/p2p.go
  47. 7
      scripts/go_executable_build.sh
  48. 9
      staking/types/commission.go
  49. 1
      staking/types/decimal_test.go
  50. 247
      staking/types/delegation.go
  51. 232
      staking/types/messages.go
  52. 413
      staking/types/messages_test.go
  53. 199
      staking/types/sign.go
  54. 39
      staking/types/staking_transaction.go
  55. 110
      staking/types/transaction.go
  56. 17
      staking/types/validator.go
  57. 19
      test/chain/main.go

@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/harmony-one/harmony/accounts" "github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
staking "github.com/harmony-one/harmony/staking/types"
) )
// ErrLocked ... // ErrLocked ...
@ -299,6 +300,20 @@ func (ks *KeyStore) SignHashWithPassphrase(a accounts.Account, passphrase string
return crypto.Sign(hash, key.PrivateKey) return crypto.Sign(hash, key.PrivateKey)
} }
// SignStakingTx signs a staking transaction, only EIP155 based signer
func (ks *KeyStore) SignStakingTx(
a accounts.Account,
tx *staking.StakingTransaction,
chainID *big.Int) (*staking.StakingTransaction, error) {
ks.mu.RLock()
defer ks.mu.RUnlock()
unlockedKey, found := ks.unlocked[a.Address]
if !found {
return nil, ErrLocked
}
return staking.Sign(tx, staking.NewEIP155Signer(chainID), unlockedKey.PrivateKey)
}
// SignTxWithPassphrase signs the transaction if the private key matching the // SignTxWithPassphrase signs the transaction if the private key matching the
// given address can be decrypted with the given passphrase. // given address can be decrypted with the given passphrase.
func (ks *KeyStore) SignTxWithPassphrase(a accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { func (ks *KeyStore) SignTxWithPassphrase(a accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {

@ -2,7 +2,6 @@ package service
import ( import (
nodeconfig "github.com/harmony-one/harmony/internal/configs/node" nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/p2p"
) )
// NodeConfig defines a structure of node configuration // NodeConfig defines a structure of node configuration
@ -11,37 +10,37 @@ import (
// cyclic imports // cyclic imports
type NodeConfig struct { type NodeConfig struct {
// The three groupID design, please refer to https://github.com/harmony-one/harmony/blob/master/node/node.md#libp2p-integration // The three groupID design, please refer to https://github.com/harmony-one/harmony/blob/master/node/node.md#libp2p-integration
Beacon p2p.GroupID // the beacon group ID Beacon nodeconfig.GroupID // the beacon group ID
ShardGroupID p2p.GroupID // the group ID of the shard ShardGroupID nodeconfig.GroupID // the group ID of the shard
Client p2p.GroupID // the client group ID of the shard Client nodeconfig.GroupID // the client group ID of the shard
IsClient bool // whether this node is a client node, such as wallet/txgen IsClient bool // whether this node is a client node, such as wallet/txgen
IsBeacon bool // whether this node is a beacon node or not IsBeacon bool // whether this node is a beacon node or not
ShardID uint32 // shardID of this node ShardID uint32 // shardID of this node
Actions map[p2p.GroupID]p2p.ActionType // actions on the groups Actions map[nodeconfig.GroupID]nodeconfig.ActionType // actions on the groups
PushgatewayIP string // prometheus pushgateway ip PushgatewayIP string // prometheus pushgateway ip
PushgatewayPort string // prometheus pushgateway port PushgatewayPort string // prometheus pushgateway port
MetricsFlag bool // flag to collect metrics or not MetricsFlag bool // flag to collect metrics or not
} }
// GroupIDShards is a map of ShardGroupID ID // GroupIDShards is a map of ShardGroupID ID
// key is the shard ID // key is the shard ID
// value is the corresponding group ID // value is the corresponding group ID
var ( var (
GroupIDShards map[p2p.ShardID]p2p.GroupID GroupIDShards map[nodeconfig.ShardID]nodeconfig.GroupID
GroupIDShardClients map[p2p.ShardID]p2p.GroupID GroupIDShardClients map[nodeconfig.ShardID]nodeconfig.GroupID
) )
func init() { func init() {
GroupIDShards = make(map[p2p.ShardID]p2p.GroupID) GroupIDShards = make(map[nodeconfig.ShardID]nodeconfig.GroupID)
GroupIDShardClients = make(map[p2p.ShardID]p2p.GroupID) GroupIDShardClients = make(map[nodeconfig.ShardID]nodeconfig.GroupID)
// init beacon chain group IDs // init beacon chain group IDs
GroupIDShards[0] = p2p.GroupIDBeacon GroupIDShards[0] = nodeconfig.NewGroupIDByShardID(0)
GroupIDShardClients[0] = p2p.GroupIDBeaconClient GroupIDShardClients[0] = nodeconfig.NewClientGroupIDByShardID(0)
for i := 1; i < nodeconfig.MaxShards; i++ { for i := 1; i < nodeconfig.MaxShards; i++ {
sid := p2p.ShardID(i) sid := nodeconfig.ShardID(i)
GroupIDShards[sid] = p2p.NewGroupIDByShardID(sid) GroupIDShards[sid] = nodeconfig.NewGroupIDByShardID(sid)
GroupIDShardClients[sid] = p2p.NewClientGroupIDByShardID(sid) GroupIDShardClients[sid] = nodeconfig.NewClientGroupIDByShardID(sid)
} }
} }

@ -18,9 +18,9 @@ type Service struct {
host p2p.Host host p2p.Host
peerChan chan p2p.Peer peerChan chan p2p.Peer
stopChan chan struct{} stopChan chan struct{}
actionChan chan p2p.GroupAction actionChan chan nodeconfig.GroupAction
config service.NodeConfig config service.NodeConfig
actions map[p2p.GroupID]p2p.ActionType actions map[nodeconfig.GroupID]nodeconfig.ActionType
messageChan chan *msg_pb.Message messageChan chan *msg_pb.Message
addBeaconPeerFunc func(*p2p.Peer) bool addBeaconPeerFunc func(*p2p.Peer) bool
} }
@ -34,9 +34,9 @@ func New(h p2p.Host, config service.NodeConfig, peerChan chan p2p.Peer, addPeer
host: h, host: h,
peerChan: peerChan, peerChan: peerChan,
stopChan: make(chan struct{}), stopChan: make(chan struct{}),
actionChan: make(chan p2p.GroupAction), actionChan: make(chan nodeconfig.GroupAction),
config: config, config: config,
actions: make(map[p2p.GroupID]p2p.ActionType), actions: make(map[nodeconfig.GroupID]nodeconfig.ActionType),
addBeaconPeerFunc: addPeer, addBeaconPeerFunc: addPeer,
} }
} }
@ -58,7 +58,7 @@ func (s *Service) StopService() {
// NotifyService receives notification from service manager // NotifyService receives notification from service manager
func (s *Service) NotifyService(params map[string]interface{}) { func (s *Service) NotifyService(params map[string]interface{}) {
data := params["peer"] data := params["peer"]
action, ok := data.(p2p.GroupAction) action, ok := data.(nodeconfig.GroupAction)
if !ok { if !ok {
utils.Logger().Error().Msg("Wrong data type passed to NotifyService") utils.Logger().Error().Msg("Wrong data type passed to NotifyService")
return return
@ -117,18 +117,14 @@ func (s *Service) contactP2pPeers() {
} }
// sentPingMessage sends a ping message to a pubsub topic // sentPingMessage sends a ping message to a pubsub topic
func (s *Service) sentPingMessage(g p2p.GroupID, msgBuf []byte) { func (s *Service) sentPingMessage(g nodeconfig.GroupID, msgBuf []byte) {
var err error var err error
if g == p2p.GroupIDBeacon || g == p2p.GroupIDBeaconClient { // The following logical will be used for 2nd stage peer discovery process
err = s.host.SendMessageToGroups([]p2p.GroupID{s.config.Beacon}, msgBuf) // do nothing when the groupID is unknown
} else { if s.config.ShardGroupID == nodeconfig.GroupIDUnknown {
// The following logical will be used for 2nd stage peer discovery process return
// do nothing when the groupID is unknown
if s.config.ShardGroupID == p2p.GroupIDUnknown {
return
}
err = s.host.SendMessageToGroups([]p2p.GroupID{s.config.ShardGroupID}, msgBuf)
} }
err = s.host.SendMessageToGroups([]nodeconfig.GroupID{s.config.ShardGroupID}, msgBuf)
if err != nil { if err != nil {
utils.Logger().Error().Err(err).Str("group", string(g)).Msg("Failed to send ping message") utils.Logger().Error().Err(err).Str("group", string(g)).Msg("Failed to send ping message")
} }

@ -339,7 +339,9 @@ func (s *Service) GetExplorerBlocks(w http.ResponseWriter, r *http.Request) {
} }
data.Blocks = append(data.Blocks, block) data.Blocks = append(data.Blocks, block)
} }
if offset*page+offset > len(data.Blocks) { if offset*page >= len(data.Blocks) {
data.Blocks = []*Block{}
} else if offset*page+offset > len(data.Blocks) {
data.Blocks = data.Blocks[offset*page:] data.Blocks = data.Blocks[offset*page:]
} else { } else {
data.Blocks = data.Blocks[offset*page : offset*page+offset] data.Blocks = data.Blocks[offset*page : offset*page+offset]
@ -458,7 +460,9 @@ func (s *ServiceAPI) GetExplorerBlocks(ctx context.Context, from, to, page, offs
} }
blocks = append(blocks, block) blocks = append(blocks, block)
} }
if offset*page+offset > len(blocks) { if offset*page >= len(blocks) {
blocks = []*Block{}
} else if offset*page+offset > len(blocks) {
blocks = blocks[offset*page:] blocks = blocks[offset*page:]
} else { } else {
blocks = blocks[offset*page : offset*page+offset] blocks = blocks[offset*page : offset*page+offset]
@ -765,7 +769,9 @@ func (s *Service) GetExplorerAddress(w http.ResponseWriter, r *http.Request) {
} }
data.Address.TXs = sentTXs data.Address.TXs = sentTXs
} }
if offset*page+offset > len(data.Address.TXs) { if offset*page >= len(data.Address.TXs) {
data.Address.TXs = []*Transaction{}
} else if offset*page+offset > len(data.Address.TXs) {
data.Address.TXs = data.Address.TXs[offset*page:] data.Address.TXs = data.Address.TXs[offset*page:]
} else { } else {
data.Address.TXs = data.Address.TXs[offset*page : offset*page+offset] data.Address.TXs = data.Address.TXs[offset*page : offset*page+offset]
@ -852,7 +858,10 @@ func (s *ServiceAPI) GetExplorerAddress(ctx context.Context, id, txView string,
} }
address.TXs = sentTXs address.TXs = sentTXs
} }
if offset*page+offset > len(address.TXs) {
if offset*page >= len(address.TXs) {
address.TXs = []*Transaction{}
} else if offset*page+offset > len(address.TXs) {
address.TXs = address.TXs[offset*page:] address.TXs = address.TXs[offset*page:]
} else { } else {
address.TXs = address.TXs[offset*page : offset*page+offset] address.TXs = address.TXs[offset*page : offset*page+offset]

@ -112,10 +112,6 @@ func (storage *Storage) Dump(block *types.Block, height uint64) {
// Store txs // Store txs
for _, tx := range block.Transactions() { for _, tx := range block.Transactions() {
if tx.To() == nil {
continue
}
explorerTransaction := GetTransaction(tx, block) explorerTransaction := GetTransaction(tx, block)
storage.UpdateTXStorage(batch, explorerTransaction, tx) storage.UpdateTXStorage(batch, explorerTransaction, tx)
storage.UpdateAddress(batch, explorerTransaction, tx) storage.UpdateAddress(batch, explorerTransaction, tx)
@ -158,7 +154,9 @@ func (storage *Storage) UpdateTXStorage(batch ethdb.Batch, explorerTransaction *
// TODO: deprecate this logic // TODO: deprecate this logic
func (storage *Storage) UpdateAddress(batch ethdb.Batch, explorerTransaction *Transaction, tx *types.Transaction) { func (storage *Storage) UpdateAddress(batch ethdb.Batch, explorerTransaction *Transaction, tx *types.Transaction) {
explorerTransaction.Type = Received explorerTransaction.Type = Received
storage.UpdateAddressStorage(batch, explorerTransaction.To, explorerTransaction, tx) if explorerTransaction.To != "" {
storage.UpdateAddressStorage(batch, explorerTransaction.To, explorerTransaction, tx)
}
explorerTransaction.Type = Sent explorerTransaction.Type = Sent
storage.UpdateAddressStorage(batch, explorerTransaction.From, explorerTransaction, tx) storage.UpdateAddressStorage(batch, explorerTransaction.From, explorerTransaction, tx)
} }

@ -5,10 +5,8 @@ import (
"math/big" "math/big"
"strconv" "strconv"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
common2 "github.com/harmony-one/harmony/internal/common" "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
) )
@ -114,20 +112,27 @@ func NewBlock(block *types.Block, height int) *Block {
// GetTransaction ... // GetTransaction ...
func GetTransaction(tx *types.Transaction, addressBlock *types.Block) *Transaction { func GetTransaction(tx *types.Transaction, addressBlock *types.Block) *Transaction {
if tx.To() == nil {
return nil
}
msg, err := tx.AsMessage(types.NewEIP155Signer(tx.ChainID())) msg, err := tx.AsMessage(types.NewEIP155Signer(tx.ChainID()))
if err != nil { if err != nil {
utils.Logger().Error().Err(err).Msg("Error when parsing tx into message") utils.Logger().Error().Err(err).Msg("Error when parsing tx into message")
} }
gasFee := big.NewInt(0) gasFee := big.NewInt(0)
gasFee = gasFee.Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas())) gasFee = gasFee.Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))
to := ""
if msg.To() != nil {
if to, err = common.AddressToBech32(*msg.To()); err != nil {
return nil
}
}
from := ""
if from, err = common.AddressToBech32(msg.From()); err != nil {
return nil
}
return &Transaction{ return &Transaction{
ID: tx.Hash().Hex(), ID: tx.Hash().Hex(),
Timestamp: strconv.Itoa(int(addressBlock.Time().Int64() * 1000)), Timestamp: strconv.Itoa(int(addressBlock.Time().Int64() * 1000)),
From: common2.MustAddressToBech32(common.HexToAddress(msg.From().Hex())), From: from,
To: common2.MustAddressToBech32(common.HexToAddress(msg.To().Hex())), To: to,
Value: msg.Value(), Value: msg.Value(),
Bytes: strconv.Itoa(int(tx.Size())), Bytes: strconv.Itoa(int(tx.Size())),
Data: hex.EncodeToString(tx.Data()), Data: hex.EncodeToString(tx.Data()),

@ -8,7 +8,6 @@ import (
"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"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node" nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/p2p"
) )
type SupportSyncingTest struct { type SupportSyncingTest struct {
@ -102,8 +101,8 @@ func TestStopServices(t *testing.T) {
} }
func TestInit(t *testing.T) { func TestInit(t *testing.T) {
if GroupIDShards[p2p.ShardID(0)] != p2p.GroupIDBeacon { if GroupIDShards[nodeconfig.ShardID(0)] != nodeconfig.NewGroupIDByShardID(0) {
t.Errorf("GroupIDShards[0]: %v != GroupIDBeacon: %v", GroupIDShards[p2p.ShardID(0)], p2p.GroupIDBeacon) t.Errorf("GroupIDShards[0]: %v != GroupIDBeacon: %v", GroupIDShards[nodeconfig.ShardID(0)], nodeconfig.NewGroupIDByShardID(0))
} }
if len(GroupIDShards) != nodeconfig.MaxShards { if len(GroupIDShards) != nodeconfig.MaxShards {
t.Errorf("len(GroupIDShards): %v != TotalShards: %v", len(GroupIDShards), nodeconfig.MaxShards) t.Errorf("len(GroupIDShards): %v != TotalShards: %v", len(GroupIDShards), nodeconfig.MaxShards)

@ -12,6 +12,7 @@ import (
"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"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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"
badger "github.com/ipfs/go-ds-badger" badger "github.com/ipfs/go-ds-badger"
@ -25,7 +26,7 @@ import (
// Service is the network info service. // Service is the network info service.
type Service struct { type Service struct {
Host p2p.Host Host p2p.Host
Rendezvous p2p.GroupID Rendezvous nodeconfig.GroupID
bootnodes utils.AddrList bootnodes utils.AddrList
dht *libp2pdht.IpfsDHT dht *libp2pdht.IpfsDHT
cancel context.CancelFunc cancel context.CancelFunc
@ -61,7 +62,7 @@ const (
// New returns role conversion service. If dataStorePath is not empty, it // New returns role conversion service. If dataStorePath is not empty, it
// points to a persistent database directory to use. // points to a persistent database directory to use.
func New( func New(
h p2p.Host, rendezvous p2p.GroupID, peerChan chan p2p.Peer, h p2p.Host, rendezvous nodeconfig.GroupID, peerChan chan p2p.Peer,
bootnodes utils.AddrList, dataStorePath string, bootnodes utils.AddrList, dataStorePath string,
) (*Service, error) { ) (*Service, error) {
var cancel context.CancelFunc var cancel context.CancelFunc
@ -100,7 +101,7 @@ func New(
// MustNew is a panic-on-error version of New. // MustNew is a panic-on-error version of New.
func MustNew( func MustNew(
h p2p.Host, rendezvous p2p.GroupID, peerChan chan p2p.Peer, h p2p.Host, rendezvous nodeconfig.GroupID, peerChan chan p2p.Peer,
bootnodes utils.AddrList, dataStorePath string, bootnodes utils.AddrList, dataStorePath string,
) *Service { ) *Service {
service, err := New(h, rendezvous, peerChan, bootnodes, dataStorePath) service, err := New(h, rendezvous, peerChan, bootnodes, dataStorePath)
@ -167,7 +168,10 @@ func (s *Service) Init() error {
utils.Logger().Info().Str("Rendezvous", string(s.Rendezvous)).Msg("Announcing ourselves...") utils.Logger().Info().Str("Rendezvous", string(s.Rendezvous)).Msg("Announcing ourselves...")
s.discovery = libp2pdis.NewRoutingDiscovery(s.dht) s.discovery = libp2pdis.NewRoutingDiscovery(s.dht)
libp2pdis.Advertise(ctx, s.discovery, string(s.Rendezvous)) libp2pdis.Advertise(ctx, s.discovery, string(s.Rendezvous))
libp2pdis.Advertise(ctx, s.discovery, string(p2p.GroupIDBeaconClient))
// Everyone is beacon client, which means everyone is connected via beacon client topic
// 0 is beacon chain FIXME: use a constant
libp2pdis.Advertise(ctx, s.discovery, string(nodeconfig.NewClientGroupIDByShardID(0)))
utils.Logger().Info().Msg("Successfully announced!") utils.Logger().Info().Msg("Successfully announced!")
return nil return nil
@ -193,7 +197,8 @@ func (s *Service) DoService() {
return return
case <-tick.C: case <-tick.C:
libp2pdis.Advertise(ctx, s.discovery, string(s.Rendezvous)) libp2pdis.Advertise(ctx, s.discovery, string(s.Rendezvous))
libp2pdis.Advertise(ctx, s.discovery, string(p2p.GroupIDBeaconClient)) // 0 is beacon chain FIXME: use a constant
libp2pdis.Advertise(ctx, s.discovery, string(nodeconfig.NewClientGroupIDByShardID(0)))
utils.Logger().Info().Str("Rendezvous", string(s.Rendezvous)).Msg("Successfully announced!") utils.Logger().Info().Str("Rendezvous", string(s.Rendezvous)).Msg("Successfully announced!")
default: default:
var err error var err error

@ -6,6 +6,7 @@ import (
"github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/crypto/bls"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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/p2p/p2pimpl" "github.com/harmony-one/harmony/p2p/p2pimpl"
@ -28,7 +29,7 @@ func TestService(t *testing.T) {
t.Fatal("unable to new host in harmony") t.Fatal("unable to new host in harmony")
} }
s, err := New(host, p2p.GroupIDBeaconClient, nil, nil, "") s, err := New(host, nodeconfig.GroupIDBeaconClient, nil, nil, "")
if err != nil { if err != nil {
t.Fatalf("New() failed: %s", err) t.Fatalf("New() failed: %s", err)
} }

@ -119,9 +119,9 @@ func setUpTXGen() *node.Node {
} }
txGen.NodeConfig.SetRole(nodeconfig.ClientNode) txGen.NodeConfig.SetRole(nodeconfig.ClientNode)
if shardID == 0 { if shardID == 0 {
txGen.NodeConfig.SetShardGroupID(p2p.GroupIDBeacon) txGen.NodeConfig.SetShardGroupID(nodeconfig.GroupIDBeacon)
} else { } else {
txGen.NodeConfig.SetShardGroupID(p2p.NewGroupIDByShardID(p2p.ShardID(shardID))) txGen.NodeConfig.SetShardGroupID(nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(shardID)))
} }
txGen.NodeConfig.SetIsClient(true) txGen.NodeConfig.SetIsClient(true)
@ -289,10 +289,10 @@ func SendTxsToShard(clientNode *node.Node, txs types.Transactions, shardID uint3
msg := proto_node.ConstructTransactionListMessageAccount(txs) msg := proto_node.ConstructTransactionListMessageAccount(txs)
var err error var err error
if shardID == 0 { if shardID == 0 {
err = clientNode.GetHost().SendMessageToGroups([]p2p.GroupID{p2p.GroupIDBeaconClient}, p2p_host.ConstructP2pMessage(byte(0), msg)) err = clientNode.GetHost().SendMessageToGroups([]nodeconfig.GroupID{nodeconfig.GroupIDBeaconClient}, p2p_host.ConstructP2pMessage(byte(0), msg))
} else { } else {
clientGroup := p2p.NewClientGroupIDByShardID(p2p.ShardID(shardID)) clientGroup := nodeconfig.NewClientGroupIDByShardID(nodeconfig.ShardID(shardID))
err = clientNode.GetHost().SendMessageToGroups([]p2p.GroupID{clientGroup}, p2p_host.ConstructP2pMessage(byte(0), msg)) err = clientNode.GetHost().SendMessageToGroups([]nodeconfig.GroupID{clientGroup}, p2p_host.ConstructP2pMessage(byte(0), msg))
} }
if err != nil { if err != nil {
utils.Logger().Debug(). utils.Logger().Debug().

@ -935,9 +935,9 @@ func clearKeystore() {
// submitTransaction submits the transaction to the Harmony network // submitTransaction submits the transaction to the Harmony network
func submitTransaction(tx *types.Transaction, walletNode *node.Node, shardID uint32) error { func submitTransaction(tx *types.Transaction, walletNode *node.Node, shardID uint32) error {
msg := proto_node.ConstructTransactionListMessageAccount(types.Transactions{tx}) msg := proto_node.ConstructTransactionListMessageAccount(types.Transactions{tx})
clientGroup := p2p.NewClientGroupIDByShardID(p2p.ShardID(shardID)) clientGroup := nodeconfig.NewClientGroupIDByShardID(nodeconfig.ShardID(shardID))
err := walletNode.GetHost().SendMessageToGroups([]p2p.GroupID{clientGroup}, p2p_host.ConstructP2pMessage(byte(0), msg)) err := walletNode.GetHost().SendMessageToGroups([]nodeconfig.GroupID{clientGroup}, p2p_host.ConstructP2pMessage(byte(0), msg))
if err != nil { if err != nil {
fmt.Printf("Error in SubmitTransaction: %v\n", err) fmt.Printf("Error in SubmitTransaction: %v\n", err)
return err return err

@ -457,9 +457,9 @@ func clearKeystore() {
// submitTransaction submits the transaction to the Harmony network // submitTransaction submits the transaction to the Harmony network
func submitTransaction(tx *types.Transaction, walletNode *node.Node, shardID uint32) error { func submitTransaction(tx *types.Transaction, walletNode *node.Node, shardID uint32) error {
msg := proto_node.ConstructTransactionListMessageAccount(types.Transactions{tx}) msg := proto_node.ConstructTransactionListMessageAccount(types.Transactions{tx})
clientGroup := p2p.NewClientGroupIDByShardID(p2p.ShardID(shardID)) clientGroup := nodeconfig.NewClientGroupIDByShardID(nodeconfig.ShardID(shardID))
err := walletNode.GetHost().SendMessageToGroups([]p2p.GroupID{clientGroup}, p2p_host.ConstructP2pMessage(byte(0), msg)) err := walletNode.GetHost().SendMessageToGroups([]nodeconfig.GroupID{clientGroup}, p2p_host.ConstructP2pMessage(byte(0), msg))
if err != nil { if err != nil {
fmt.Printf("Error in SubmitTransaction: %v\n", err) fmt.Printf("Error in SubmitTransaction: %v\n", err)
return err return err

@ -35,6 +35,7 @@ import (
"github.com/harmony-one/harmony/p2p/p2pimpl" "github.com/harmony-one/harmony/p2p/p2pimpl"
) )
// Version string variables
var ( var (
version string version string
builtBy string builtBy string
@ -42,6 +43,11 @@ var (
commit string commit string
) )
// Host
var (
myHost p2p.Host
)
// InitLDBDatabase initializes a LDBDatabase. isGenesis=true will return the beacon chain database for normal shard nodes // InitLDBDatabase initializes a LDBDatabase. isGenesis=true will return the beacon chain database for normal shard nodes
func InitLDBDatabase(ip string, port string, freshDB bool, isBeacon bool) (*ethdb.LDBDatabase, error) { func InitLDBDatabase(ip string, port string, freshDB bool, isBeacon bool) (*ethdb.LDBDatabase, error) {
var dbFileName string var dbFileName string
@ -64,6 +70,7 @@ func printVersion() {
os.Exit(0) os.Exit(0)
} }
// Flags
var ( var (
ip = flag.String("ip", "127.0.0.1", "ip of the node") ip = flag.String("ip", "127.0.0.1", "ip of the node")
port = flag.String("port", "9000", "port of the node.") port = flag.String("port", "9000", "port of the node.")
@ -262,11 +269,12 @@ func createGlobalConfig() *nodeconfig.ConfigType {
if err != nil { if err != nil {
panic(err) panic(err)
} }
nodeConfig.SelfPeer = p2p.Peer{IP: *ip, Port: *port, ConsensusPubKey: nodeConfig.ConsensusPubKey}
nodeConfig.Host, err = p2pimpl.NewHost(&nodeConfig.SelfPeer, nodeConfig.P2pPriKey) selfPeer := p2p.Peer{IP: *ip, Port: *port, ConsensusPubKey: nodeConfig.ConsensusPubKey}
myHost, err = p2pimpl.NewHost(&selfPeer, nodeConfig.P2pPriKey)
if *logConn && nodeConfig.GetNetworkType() != nodeconfig.Mainnet { if *logConn && nodeConfig.GetNetworkType() != nodeconfig.Mainnet {
nodeConfig.Host.GetP2PHost().Network().Notify(utils.NewConnLogger(utils.GetLogInstance())) myHost.GetP2PHost().Network().Notify(utils.NewConnLogger(utils.GetLogInstance()))
} }
if err != nil { if err != nil {
panic("unable to new host in harmony") panic("unable to new host in harmony")
@ -281,7 +289,7 @@ func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node {
// Consensus object. // Consensus object.
// TODO: consensus object shouldn't start here // TODO: consensus object shouldn't start here
// TODO(minhdoan): During refactoring, found out that the peers list is actually empty. Need to clean up the logic of consensus later. // TODO(minhdoan): During refactoring, found out that the peers list is actually empty. Need to clean up the logic of consensus later.
currentConsensus, err := consensus.New(nodeConfig.Host, nodeConfig.ShardID, nodeConfig.Leader, nodeConfig.ConsensusPriKey) currentConsensus, err := consensus.New(myHost, nodeConfig.ShardID, p2p.Peer{}, nodeConfig.ConsensusPriKey)
currentConsensus.SelfAddress = common.ParseAddr(initialAccount.Address) currentConsensus.SelfAddress = common.ParseAddr(initialAccount.Address)
if err != nil { if err != nil {
@ -302,7 +310,7 @@ func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node {
// Current node. // Current node.
chainDBFactory := &shardchain.LDBFactory{RootDir: nodeConfig.DBDir} chainDBFactory := &shardchain.LDBFactory{RootDir: nodeConfig.DBDir}
currentNode := node.New(nodeConfig.Host, currentConsensus, chainDBFactory, *isArchival) currentNode := node.New(myHost, currentConsensus, chainDBFactory, *isArchival)
switch { switch {
case *networkType == nodeconfig.Localnet: case *networkType == nodeconfig.Localnet:
@ -338,21 +346,21 @@ func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node {
currentNode.NodeConfig.SetPushgatewayPort(nodeConfig.PushgatewayPort) currentNode.NodeConfig.SetPushgatewayPort(nodeConfig.PushgatewayPort)
currentNode.NodeConfig.SetMetricsFlag(nodeConfig.MetricsFlag) currentNode.NodeConfig.SetMetricsFlag(nodeConfig.MetricsFlag)
currentNode.NodeConfig.SetBeaconGroupID(p2p.NewGroupIDByShardID(0)) currentNode.NodeConfig.SetBeaconGroupID(nodeconfig.NewGroupIDByShardID(0))
switch *nodeType { switch *nodeType {
case "explorer": case "explorer":
currentNode.NodeConfig.SetRole(nodeconfig.ExplorerNode) currentNode.NodeConfig.SetRole(nodeconfig.ExplorerNode)
currentNode.NodeConfig.SetShardGroupID(p2p.NewGroupIDByShardID(p2p.ShardID(*shardID))) currentNode.NodeConfig.SetShardGroupID(nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(*shardID)))
currentNode.NodeConfig.SetClientGroupID(p2p.NewClientGroupIDByShardID(p2p.ShardID(*shardID))) currentNode.NodeConfig.SetClientGroupID(nodeconfig.NewClientGroupIDByShardID(nodeconfig.ShardID(*shardID)))
case "validator": case "validator":
currentNode.NodeConfig.SetRole(nodeconfig.Validator) currentNode.NodeConfig.SetRole(nodeconfig.Validator)
if nodeConfig.ShardID == 0 { if nodeConfig.ShardID == 0 {
currentNode.NodeConfig.SetShardGroupID(p2p.GroupIDBeacon) currentNode.NodeConfig.SetShardGroupID(nodeconfig.NewGroupIDByShardID(0))
currentNode.NodeConfig.SetClientGroupID(p2p.GroupIDBeaconClient) currentNode.NodeConfig.SetClientGroupID(nodeconfig.NewClientGroupIDByShardID(0))
} else { } else {
currentNode.NodeConfig.SetShardGroupID(p2p.NewGroupIDByShardID(p2p.ShardID(nodeConfig.ShardID))) currentNode.NodeConfig.SetShardGroupID(nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(nodeConfig.ShardID)))
currentNode.NodeConfig.SetClientGroupID(p2p.NewClientGroupIDByShardID(p2p.ShardID(nodeConfig.ShardID))) currentNode.NodeConfig.SetClientGroupID(nodeconfig.NewClientGroupIDByShardID(nodeconfig.ShardID(nodeConfig.ShardID)))
} }
} }
currentNode.NodeConfig.ConsensusPubKey = nodeConfig.ConsensusPubKey currentNode.NodeConfig.ConsensusPubKey = nodeConfig.ConsensusPubKey
@ -479,7 +487,7 @@ func main() {
Str("BeaconGroupID", nodeConfig.GetBeaconGroupID().String()). Str("BeaconGroupID", nodeConfig.GetBeaconGroupID().String()).
Str("ClientGroupID", nodeConfig.GetClientGroupID().String()). Str("ClientGroupID", nodeConfig.GetClientGroupID().String()).
Str("Role", currentNode.NodeConfig.Role().String()). Str("Role", currentNode.NodeConfig.Role().String()).
Str("multiaddress", fmt.Sprintf("/ip4/%s/tcp/%s/p2p/%s", *ip, *port, nodeConfig.Host.GetID().Pretty())). Str("multiaddress", fmt.Sprintf("/ip4/%s/tcp/%s/p2p/%s", *ip, *port, myHost.GetID().Pretty())).
Msg(startMsg) Msg(startMsg)
if *enableMemProfiling { if *enableMemProfiling {

@ -0,0 +1,24 @@
package main
import (
"fmt"
"os"
)
var (
version string
commit string
builtAt string
builtBy string
)
func main() {
if os.Args[1] == "-version" {
fmt.Fprintf(os.Stderr, versionS()+"\n")
os.Exit(0)
}
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(-1)
}
}

@ -0,0 +1,173 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"net/http"
"os"
"path"
"strconv"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/accounts/keystore"
"github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
"github.com/spf13/cobra"
)
const (
keystoreDir = ".hmy/keystore"
stakingRPC = "hmy_sendRawStakingTransaction"
)
type staker struct{}
var (
queryID = 0
s = &staker{}
localNetChain = big.NewInt(2)
dAddr = common.ParseAddr(testAccount)
)
const (
// Harmony protocol assume beacon chain shard is only place to send
// staking, later need to consider logic when beacon chain shard rotates
stakingShard = 0
testAccount = "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9"
testBLSPubKey = "b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611"
testAccountPassword = ""
)
func (s *staker) run(cmd *cobra.Command, args []string) error {
scryptN := keystore.StandardScryptN
scryptP := keystore.StandardScryptP
ks := keystore.NewKeyStore(keystoreDir, scryptN, scryptP)
account := accounts.Account{Address: dAddr}
ks.Unlock(account, testAccountPassword)
gasPrice := big.NewInt(0)
stakePayloadMaker := func() (staking.Directive, interface{}) {
p := &bls.PublicKey{}
p.DeserializeHexStr(testBLSPubKey)
pub := shard.BlsPublicKey{}
pub.FromLibBLSPublicKey(p)
return staking.DirectiveNewValidator, staking.NewValidator{
Description: staking.Description{
Name: "something",
Identity: "something else",
Website: "some site, harmony.one",
SecurityContact: "mr.smith",
Details: "blah blah details",
},
CommissionRates: staking.CommissionRates{
Rate: staking.NewDec(100),
MaxRate: staking.NewDec(150),
MaxChangeRate: staking.NewDec(5),
},
MinSelfDelegation: big.NewInt(10),
StakingAddress: common.Address(dAddr),
PubKey: pub,
Amount: big.NewInt(100),
}
// return message.DirectiveDelegate, message.Delegate{
// common.Address(dAddr),
// common.Address(dAddr),
// big.NewInt(10),
// }
}
stakingTx, err := staking.NewStakingTransaction(2, 100, gasPrice, stakePayloadMaker)
if err != nil {
return err
}
signed, oops := ks.SignStakingTx(account, stakingTx, localNetChain)
if oops != nil {
return oops
}
enc, oops1 := rlp.EncodeToBytes(signed)
if oops1 != nil {
return oops1
}
tx := new(staking.StakingTransaction)
if err := rlp.DecodeBytes(enc, tx); err != nil {
return err
}
fmt.Printf("In Client side: %+v\n", tx)
// return nil
rlp.DecodeBytes(enc, tx)
hexSignature := hexutil.Encode(enc)
param := []interface{}{hexSignature}
result, reqOops := baseRequest(stakingRPC, "http://localhost:9500", param)
fmt.Println(string(result))
return reqOops
}
func versionS() string {
return fmt.Sprintf(
"Harmony (C) 2019. %v, version %v-%v (%v %v)",
path.Base(os.Args[0]), version, commit, builtBy, builtAt,
)
}
func (s *staker) preRunInit(cmd *cobra.Command, args []string) error {
// Just in case need to do some kind of setup that needs to propagate downward
return nil
}
func baseRequest(method, node string, params interface{}) ([]byte, error) {
requestBody, _ := json.Marshal(map[string]interface{}{
"jsonrpc": "2.0",
"id": strconv.Itoa(queryID),
"method": method,
"params": params,
})
resp, err := http.Post(node, "application/json", bytes.NewBuffer(requestBody))
fmt.Printf("URL: %s, Request Body: %s\n\n", node, string(requestBody))
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
queryID++
fmt.Printf("URL: %s, Response Body: %s\n\n", node, string(body))
return body, err
}
func init() {
rootCmd.AddCommand(&cobra.Command{
Use: "staking-iterate",
Short: "run through staking process",
PersistentPreRunE: s.preRunInit,
RunE: s.run,
})
rootCmd.AddCommand(&cobra.Command{
Use: "version",
Short: "Show version",
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, versionS()+"\n")
os.Exit(0)
},
})
}
var (
rootCmd = &cobra.Command{
Use: "staking-standalone",
SilenceUsage: true,
Long: "testing staking quickly",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
)

@ -5,6 +5,7 @@ import (
"time" "time"
msg_pb "github.com/harmony-one/harmony/api/proto/message" msg_pb "github.com/harmony-one/harmony/api/proto/message"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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"
) )
@ -28,7 +29,7 @@ type MessageSender struct {
// MessageRetry controls the message that can be retried // MessageRetry controls the message that can be retried
type MessageRetry struct { type MessageRetry struct {
blockNum uint64 // The block number this message is for blockNum uint64 // The block number this message is for
groups []p2p.GroupID groups []nodeconfig.GroupID
p2pMsg []byte p2pMsg []byte
msgType msg_pb.MessageType msgType msg_pb.MessageType
retryCount int retryCount int
@ -58,7 +59,7 @@ func (sender *MessageSender) Reset(blockNum uint64) {
} }
// SendWithRetry sends message with retry logic. // SendWithRetry sends message with retry logic.
func (sender *MessageSender) SendWithRetry(blockNum uint64, msgType msg_pb.MessageType, groups []p2p.GroupID, p2pMsg []byte) error { func (sender *MessageSender) SendWithRetry(blockNum uint64, msgType msg_pb.MessageType, groups []nodeconfig.GroupID, p2pMsg []byte) error {
willRetry := sender.retryTimes != 0 willRetry := sender.retryTimes != 0
msgRetry := MessageRetry{blockNum: blockNum, groups: groups, p2pMsg: p2pMsg, msgType: msgType, retryCount: 0, isActive: willRetry} msgRetry := MessageRetry{blockNum: blockNum, groups: groups, p2pMsg: p2pMsg, msgType: msgType, retryCount: 0, isActive: willRetry}
if willRetry { if willRetry {
@ -71,7 +72,7 @@ func (sender *MessageSender) SendWithRetry(blockNum uint64, msgType msg_pb.Messa
} }
// SendWithoutRetry sends message without retry logic. // SendWithoutRetry sends message without retry logic.
func (sender *MessageSender) SendWithoutRetry(groups []p2p.GroupID, p2pMsg []byte) error { func (sender *MessageSender) SendWithoutRetry(groups []nodeconfig.GroupID, p2pMsg []byte) error {
return sender.host.SendMessageToGroups(groups, p2pMsg) return sender.host.SendMessageToGroups(groups, p2pMsg)
} }

@ -19,9 +19,9 @@ import (
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
vrf_bls "github.com/harmony-one/harmony/crypto/vrf/bls" vrf_bls "github.com/harmony-one/harmony/crypto/vrf/bls"
"github.com/harmony-one/harmony/internal/chain" "github.com/harmony-one/harmony/internal/chain"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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/p2p"
"github.com/harmony-one/harmony/p2p/host" "github.com/harmony-one/harmony/p2p/host"
) )
@ -134,9 +134,9 @@ func (consensus *Consensus) announce(block *types.Block) {
// Construct broadcast p2p message // Construct broadcast p2p message
if err := consensus.msgSender.SendWithRetry(consensus.blockNum, msg_pb.MessageType_ANNOUNCE, []p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil { if err := consensus.msgSender.SendWithRetry(consensus.blockNum, msg_pb.MessageType_ANNOUNCE, []nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil {
utils.Logger().Warn(). utils.Logger().Warn().
Str("groupID", string(p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID)))). Str("groupID", string(nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID)))).
Msg("[Announce] Cannot send announce message") Msg("[Announce] Cannot send announce message")
} else { } else {
utils.Logger().Info(). utils.Logger().Info().
@ -235,7 +235,7 @@ func (consensus *Consensus) onAnnounce(msg *msg_pb.Message) {
logMsgs := consensus.PbftLog.GetMessagesByTypeSeqView(msg_pb.MessageType_ANNOUNCE, recvMsg.BlockNum, recvMsg.ViewID) logMsgs := consensus.PbftLog.GetMessagesByTypeSeqView(msg_pb.MessageType_ANNOUNCE, recvMsg.BlockNum, recvMsg.ViewID)
if len(logMsgs) > 0 { if len(logMsgs) > 0 {
if logMsgs[0].BlockHash != recvMsg.BlockHash { if logMsgs[0].BlockHash != recvMsg.BlockHash && logMsgs[0].SenderPubkey.IsEqual(recvMsg.SenderPubkey) {
utils.Logger().Debug(). utils.Logger().Debug().
Str("leaderKey", consensus.LeaderPubKey.SerializeToHexStr()). Str("leaderKey", consensus.LeaderPubKey.SerializeToHexStr()).
Msg("[OnAnnounce] Leader is malicious") Msg("[OnAnnounce] Leader is malicious")
@ -284,7 +284,7 @@ func (consensus *Consensus) prepare() {
msgToSend := consensus.constructPrepareMessage() msgToSend := consensus.constructPrepareMessage()
// TODO: this will not return immediatey, may block // TODO: this will not return immediatey, may block
if err := consensus.msgSender.SendWithoutRetry([]p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil { if err := consensus.msgSender.SendWithoutRetry([]nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil {
utils.Logger().Warn().Err(err).Msg("[OnAnnounce] Cannot send prepare message") utils.Logger().Warn().Err(err).Msg("[OnAnnounce] Cannot send prepare message")
} else { } else {
utils.Logger().Info(). utils.Logger().Info().
@ -408,7 +408,7 @@ func (consensus *Consensus) onPrepare(msg *msg_pb.Message) {
return return
} }
if err := consensus.msgSender.SendWithRetry(consensus.blockNum, msg_pb.MessageType_PREPARED, []p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil { if err := consensus.msgSender.SendWithRetry(consensus.blockNum, msg_pb.MessageType_PREPARED, []nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil {
utils.Logger().Warn().Msg("[OnPrepare] Cannot send prepared message") utils.Logger().Warn().Msg("[OnPrepare] Cannot send prepared message")
} else { } else {
utils.Logger().Debug(). utils.Logger().Debug().
@ -592,7 +592,7 @@ func (consensus *Consensus) onPrepared(msg *msg_pb.Message) {
time.Sleep(consensus.delayCommit) time.Sleep(consensus.delayCommit)
} }
if err := consensus.msgSender.SendWithoutRetry([]p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil { if err := consensus.msgSender.SendWithoutRetry([]nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil {
utils.Logger().Warn().Msg("[OnPrepared] Cannot send commit message!!") utils.Logger().Warn().Msg("[OnPrepared] Cannot send commit message!!")
} else { } else {
utils.Logger().Info(). utils.Logger().Info().
@ -771,7 +771,7 @@ func (consensus *Consensus) finalizeCommits() {
} }
// if leader success finalize the block, send committed message to validators // if leader success finalize the block, send committed message to validators
if err := consensus.msgSender.SendWithRetry(block.NumberU64(), msg_pb.MessageType_COMMITTED, []p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil { if err := consensus.msgSender.SendWithRetry(block.NumberU64(), msg_pb.MessageType_COMMITTED, []nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)); err != nil {
utils.Logger().Warn().Err(err).Msg("[Finalizing] Cannot send committed message") utils.Logger().Warn().Err(err).Msg("[Finalizing] Cannot send committed message")
} else { } else {
utils.Logger().Info(). utils.Logger().Info().

@ -10,8 +10,8 @@ import (
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
msg_pb "github.com/harmony-one/harmony/api/proto/message" msg_pb "github.com/harmony-one/harmony/api/proto/message"
bls_cosi "github.com/harmony-one/harmony/crypto/bls" bls_cosi "github.com/harmony-one/harmony/crypto/bls"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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/host" "github.com/harmony-one/harmony/p2p/host"
) )
@ -187,7 +187,7 @@ func (consensus *Consensus) startViewChange(viewID uint64) {
Msg("[startViewChange]") Msg("[startViewChange]")
msgToSend := consensus.constructViewChangeMessage() msgToSend := consensus.constructViewChangeMessage()
consensus.host.SendMessageToGroups([]p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)) consensus.host.SendMessageToGroups([]nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend))
consensus.consensusTimeout[timeoutViewChange].SetDuration(duration) consensus.consensusTimeout[timeoutViewChange].SetDuration(duration)
consensus.consensusTimeout[timeoutViewChange].Start() consensus.consensusTimeout[timeoutViewChange].Start()
@ -223,6 +223,7 @@ func (consensus *Consensus) onViewChange(msg *msg_pb.Message) {
} }
// TODO: if difference is only one, new leader can still propose the same committed block to avoid another view change // TODO: if difference is only one, new leader can still propose the same committed block to avoid another view change
// TODO: new leader catchup without ignore view change message
if consensus.blockNum > recvMsg.BlockNum { if consensus.blockNum > recvMsg.BlockNum {
utils.Logger().Debug(). utils.Logger().Debug().
Uint64("MsgBlockNum", recvMsg.BlockNum). Uint64("MsgBlockNum", recvMsg.BlockNum).
@ -252,6 +253,7 @@ func (consensus *Consensus) onViewChange(msg *msg_pb.Message) {
consensus.vcLock.Lock() consensus.vcLock.Lock()
defer consensus.vcLock.Unlock() defer consensus.vcLock.Unlock()
// TODO: remove NIL type message
// add self m1 or m2 type message signature and bitmap // add self m1 or m2 type message signature and bitmap
_, ok1 := consensus.nilSigs[consensus.PubKey.SerializeToHexStr()] _, ok1 := consensus.nilSigs[consensus.PubKey.SerializeToHexStr()]
_, ok2 := consensus.bhpSigs[consensus.PubKey.SerializeToHexStr()] _, ok2 := consensus.bhpSigs[consensus.PubKey.SerializeToHexStr()]
@ -432,7 +434,7 @@ func (consensus *Consensus) onViewChange(msg *msg_pb.Message) {
Int("payloadSize", len(consensus.m1Payload)). Int("payloadSize", len(consensus.m1Payload)).
Hex("M1Payload", consensus.m1Payload). Hex("M1Payload", consensus.m1Payload).
Msg("[onViewChange] Sent NewView Message") Msg("[onViewChange] Sent NewView Message")
consensus.msgSender.SendWithRetry(consensus.blockNum, msg_pb.MessageType_NEWVIEW, []p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)) consensus.msgSender.SendWithRetry(consensus.blockNum, msg_pb.MessageType_NEWVIEW, []nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend))
consensus.viewID = recvMsg.ViewID consensus.viewID = recvMsg.ViewID
consensus.ResetViewChangeState() consensus.ResetViewChangeState()
@ -554,6 +556,7 @@ 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
// TODO: check magic number 32
if len(recvMsg.Payload) > 32 { if len(recvMsg.Payload) > 32 {
// Construct and send the commit message // Construct and send the commit message
blockNumHash := make([]byte, 8) blockNumHash := make([]byte, 8)
@ -562,7 +565,7 @@ func (consensus *Consensus) onNewView(msg *msg_pb.Message) {
msgToSend := consensus.constructCommitMessage(commitPayload) msgToSend := consensus.constructCommitMessage(commitPayload)
utils.Logger().Info().Msg("onNewView === commit") utils.Logger().Info().Msg("onNewView === commit")
consensus.host.SendMessageToGroups([]p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)) consensus.host.SendMessageToGroups([]nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend))
utils.Logger().Debug(). utils.Logger().Debug().
Str("From", consensus.phase.String()). Str("From", consensus.phase.String()).
Str("To", Commit.String()). Str("To", Commit.String()).

@ -16,7 +16,9 @@
package core package core
import "errors" import (
"github.com/pkg/errors"
)
var ( var (
// ErrKnownBlock is returned when a block to import is already known locally. // ErrKnownBlock is returned when a block to import is already known locally.
@ -35,4 +37,7 @@ var (
// ErrShardStateNotMatch is returned if the calculated shardState hash not equal that in the block header // ErrShardStateNotMatch is returned if the calculated shardState hash not equal that in the block header
ErrShardStateNotMatch = errors.New("shard state root hash not match") ErrShardStateNotMatch = errors.New("shard state root hash not match")
// ErrInvalidChainID when ChainID of signer does not match that of running node
ErrInvalidChainID = errors.New("invalid chain id for signer")
) )

@ -12,8 +12,8 @@ import (
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/crypto/vdf" "github.com/harmony-one/harmony/crypto/vdf"
"github.com/harmony-one/harmony/crypto/vrf/p256" "github.com/harmony-one/harmony/crypto/vrf/p256"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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/host" "github.com/harmony-one/harmony/p2p/host"
) )
@ -81,7 +81,7 @@ func (dRand *DRand) init(epochBlock *types.Block) {
Hex("msg", msgToSend). Hex("msg", msgToSend).
Str("leader.PubKey", dRand.leader.ConsensusPubKey.SerializeToHexStr()). Str("leader.PubKey", dRand.leader.ConsensusPubKey.SerializeToHexStr()).
Msg("[DRG] sent init") Msg("[DRG] sent init")
dRand.host.SendMessageToGroups([]p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(dRand.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)) dRand.host.SendMessageToGroups([]nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(dRand.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend))
} }
// ProcessMessageLeader dispatches messages for the leader to corresponding processors. // ProcessMessageLeader dispatches messages for the leader to corresponding processors.

@ -3,8 +3,8 @@ package drand
import ( import (
protobuf "github.com/golang/protobuf/proto" protobuf "github.com/golang/protobuf/proto"
msg_pb "github.com/harmony-one/harmony/api/proto/message" msg_pb "github.com/harmony-one/harmony/api/proto/message"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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/host" "github.com/harmony-one/harmony/p2p/host"
) )
@ -59,5 +59,5 @@ func (dRand *DRand) processInitMessage(message *msg_pb.Message) {
msgToSend := dRand.constructCommitMessage(rand, proof) msgToSend := dRand.constructCommitMessage(rand, proof)
// Send the commit message back to leader // Send the commit message back to leader
dRand.host.SendMessageToGroups([]p2p.GroupID{p2p.NewGroupIDByShardID(p2p.ShardID(dRand.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend)) dRand.host.SendMessageToGroups([]nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(dRand.ShardID))}, host.ConstructP2pMessage(byte(17), msgToSend))
} }

@ -54,6 +54,7 @@ require (
github.com/rs/zerolog v1.14.3 github.com/rs/zerolog v1.14.3
github.com/shirou/gopsutil v2.18.12+incompatible github.com/shirou/gopsutil v2.18.12+incompatible
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect
github.com/spf13/cobra v0.0.5
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc

@ -21,6 +21,7 @@ import (
"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/params"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
) )
// APIBackend An implementation of internal/hmyapi/Backend. Full client. // APIBackend An implementation of internal/hmyapi/Backend. Full client.
@ -280,3 +281,11 @@ func (b *APIBackend) ResendCx(ctx context.Context, txID common.Hash) (uint64, bo
func (b *APIBackend) IsLeader() bool { func (b *APIBackend) IsLeader() bool {
return b.hmy.nodeAPI.IsCurrentlyLeader() return b.hmy.nodeAPI.IsCurrentlyLeader()
} }
// SendStakingTx adds a staking transaction
func (b *APIBackend) SendStakingTx(
ctx context.Context,
newStakingTx *staking.StakingTransaction) error {
b.hmy.nodeAPI.AddPendingStakingTransaction(newStakingTx)
return nil
}

@ -11,6 +11,7 @@ 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/internal/params" "github.com/harmony-one/harmony/internal/params"
staking "github.com/harmony-one/harmony/staking/types"
) )
// Harmony implements the Harmony full node service. // Harmony implements the Harmony full node service.
@ -43,6 +44,7 @@ type Harmony struct {
// NodeAPI is the list of functions from node used to call rpc apis. // NodeAPI is the list of functions from node used to call rpc apis.
type NodeAPI interface { type NodeAPI interface {
AddPendingStakingTransaction(*staking.StakingTransaction)
AddPendingTransaction(newTx *types.Transaction) AddPendingTransaction(newTx *types.Transaction)
Blockchain() *core.BlockChain Blockchain() *core.BlockChain
AccountManager() *accounts.Manager AccountManager() *accounts.Manager

@ -11,8 +11,6 @@ import (
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
p2p_crypto "github.com/libp2p/go-libp2p-crypto" p2p_crypto "github.com/libp2p/go-libp2p-crypto"
"github.com/harmony-one/harmony/p2p"
) )
// Role defines a role of a node. // Role defines a role of a node.
@ -67,21 +65,20 @@ var publicRPC bool // enable public RPC access
// ConfigType is the structure of all node related configuration variables // ConfigType is the structure of all node related configuration variables
type ConfigType struct { type ConfigType struct {
// The three groupID design, please refer to https://github.com/harmony-one/harmony/blob/master/node/node.md#libp2p-integration // The three groupID design, please refer to https://github.com/harmony-one/harmony/blob/master/node/node.md#libp2p-integration
beacon p2p.GroupID // the beacon group ID beacon GroupID // the beacon group ID
group p2p.GroupID // the group ID of the shard (note: for beacon chain node, the beacon and shard group are the same) group GroupID // the group ID of the shard (note: for beacon chain node, the beacon and shard group are the same)
client p2p.GroupID // the client group ID of the shard client GroupID // the client group ID of the shard
isClient bool // whether this node is a client node, such as wallet/txgen isClient bool // whether this node is a client node, such as wallet/txgen
isBeacon bool // whether this node is beacon node doing consensus or not isBeacon bool // whether this node is beacon node doing consensus or not
ShardID uint32 // ShardID of this node; TODO ek – reviisit when resharding ShardID uint32 // ShardID of this node; TODO ek – reviisit when resharding
role Role // Role of the node role Role // Role of the node
Port string // Port of the node. Port string // Port of the node.
IP string // IP of the node. IP string // IP of the node.
MetricsFlag bool // collect and upload metrics flag MetricsFlag bool // collect and upload metrics flag
PushgatewayIP string // metrics pushgateway prometheus ip PushgatewayIP string // metrics pushgateway prometheus ip
PushgatewayPort string // metrics pushgateway prometheus port PushgatewayPort string // metrics pushgateway prometheus port
StringRole string StringRole string
Host p2p.Host
StakingPriKey *ecdsa.PrivateKey StakingPriKey *ecdsa.PrivateKey
P2pPriKey p2p_crypto.PrivKey P2pPriKey p2p_crypto.PrivKey
ConsensusPriKey *bls.SecretKey ConsensusPriKey *bls.SecretKey
@ -90,9 +87,6 @@ type ConfigType struct {
// Database directory // Database directory
DBDir string DBDir string
SelfPeer p2p.Peer
Leader p2p.Peer
networkType NetworkType networkType NetworkType
} }
@ -139,17 +133,17 @@ func (conf *ConfigType) String() string {
} }
// SetBeaconGroupID set the groupID for beacon group // SetBeaconGroupID set the groupID for beacon group
func (conf *ConfigType) SetBeaconGroupID(g p2p.GroupID) { func (conf *ConfigType) SetBeaconGroupID(g GroupID) {
conf.beacon = g conf.beacon = g
} }
// SetShardGroupID set the groupID for shard group // SetShardGroupID set the groupID for shard group
func (conf *ConfigType) SetShardGroupID(g p2p.GroupID) { func (conf *ConfigType) SetShardGroupID(g GroupID) {
conf.group = g conf.group = g
} }
// SetClientGroupID set the groupID for client group // SetClientGroupID set the groupID for client group
func (conf *ConfigType) SetClientGroupID(g p2p.GroupID) { func (conf *ConfigType) SetClientGroupID(g GroupID) {
conf.client = g conf.client = g
} }
@ -199,12 +193,12 @@ func (conf *ConfigType) GetPushgatewayPort() string {
} }
// GetBeaconGroupID returns the groupID for beacon group // GetBeaconGroupID returns the groupID for beacon group
func (conf *ConfigType) GetBeaconGroupID() p2p.GroupID { func (conf *ConfigType) GetBeaconGroupID() GroupID {
return conf.beacon return conf.beacon
} }
// GetShardGroupID returns the groupID for shard group // GetShardGroupID returns the groupID for shard group
func (conf *ConfigType) GetShardGroupID() p2p.GroupID { func (conf *ConfigType) GetShardGroupID() GroupID {
return conf.group return conf.group
} }
@ -214,7 +208,7 @@ func (conf *ConfigType) GetShardID() uint32 {
} }
// GetClientGroupID returns the groupID for client group // GetClientGroupID returns the groupID for client group
func (conf *ConfigType) GetClientGroupID() p2p.GroupID { func (conf *ConfigType) GetClientGroupID() GroupID {
return conf.client return conf.client
} }

@ -2,8 +2,6 @@ package nodeconfig
import ( import (
"testing" "testing"
"github.com/harmony-one/harmony/p2p"
) )
func TestNodeConfigSingleton(t *testing.T) { func TestNodeConfigSingleton(t *testing.T) {
@ -13,14 +11,14 @@ func TestNodeConfigSingleton(t *testing.T) {
// get the singleton variable // get the singleton variable
c := GetShardConfig(Global) c := GetShardConfig(Global)
c.SetBeaconGroupID(p2p.GroupIDBeacon) c.SetBeaconGroupID(GroupIDBeacon)
d := GetShardConfig(Global) d := GetShardConfig(Global)
g := d.GetBeaconGroupID() g := d.GetBeaconGroupID()
if g != p2p.GroupIDBeacon { if g != GroupIDBeacon {
t.Errorf("GetBeaconGroupID = %v, expected = %v", g, p2p.GroupIDBeacon) t.Errorf("GetBeaconGroupID = %v, expected = %v", g, GroupIDBeacon)
} }
} }

@ -1,12 +1,8 @@
package p2p package nodeconfig
import ( import (
"context"
"fmt" "fmt"
"io"
"strconv" "strconv"
libp2p_peer "github.com/libp2p/go-libp2p-peer"
) )
// GroupID is a multicast group ID. // GroupID is a multicast group ID.
@ -25,32 +21,50 @@ func (id GroupID) String() string {
// Const of group ID // Const of group ID
const ( const (
GroupIDBeacon GroupID = "harmony/0.0.1/node/beacon" GroupIDBeacon GroupID = "%s/0.0.1/node/beacon"
GroupIDBeaconClient GroupID = "harmony/0.0.1/client/beacon" GroupIDBeaconClient GroupID = "%s/0.0.1/client/beacon"
GroupIDShardPrefix GroupID = "harmony/0.0.1/node/shard/%s" GroupIDShardPrefix GroupID = "%s/0.0.1/node/shard/%s"
GroupIDShardClientPrefix GroupID = "harmony/0.0.1/client/shard/%s" GroupIDShardClientPrefix GroupID = "%s/0.0.1/client/shard/%s"
GroupIDGlobal GroupID = "harmony/0.0.1/node/global" GroupIDGlobal GroupID = "%s/0.0.1/node/global"
GroupIDGlobalClient GroupID = "harmony/0.0.1/node/global" GroupIDGlobalClient GroupID = "%s/0.0.1/node/global"
GroupIDUnknown GroupID = "B1acKh0lE" GroupIDUnknown GroupID = "%s/B1acKh0lE"
) )
// ShardID defines the ID of a shard // ShardID defines the ID of a shard
type ShardID uint32 type ShardID uint32
func getNetworkPrefix(shardID ShardID) (netPre string) {
switch GetShardConfig(uint32(shardID)).GetNetworkType() {
case Mainnet:
netPre = "harmony"
case Testnet:
netPre = "hmy/testnet"
case Pangaea:
netPre = "hmy/pangaea"
case Devnet:
netPre = "hmy/devnet"
case Localnet:
netPre = "hmy/local"
default:
netPre = "hmy/misc"
}
return
}
// NewGroupIDByShardID returns a new groupID for a shard // NewGroupIDByShardID returns a new groupID for a shard
func NewGroupIDByShardID(shardID ShardID) GroupID { func NewGroupIDByShardID(shardID ShardID) GroupID {
if shardID == 0 { if shardID == 0 {
return GroupIDBeacon return GroupID(fmt.Sprintf(GroupIDBeacon.String(), getNetworkPrefix(shardID)))
} }
return GroupID(fmt.Sprintf(GroupIDShardPrefix.String(), strconv.Itoa(int(shardID)))) return GroupID(fmt.Sprintf(GroupIDShardPrefix.String(), getNetworkPrefix(shardID), strconv.Itoa(int(shardID))))
} }
// NewClientGroupIDByShardID returns a new groupID for a shard's client // NewClientGroupIDByShardID returns a new groupID for a shard's client
func NewClientGroupIDByShardID(shardID ShardID) GroupID { func NewClientGroupIDByShardID(shardID ShardID) GroupID {
if shardID == 0 { if shardID == 0 {
return GroupIDBeaconClient return GroupID(fmt.Sprintf(GroupIDBeaconClient.String(), getNetworkPrefix(shardID)))
} }
return GroupID(fmt.Sprintf(GroupIDShardClientPrefix.String(), strconv.Itoa(int(shardID)))) return GroupID(fmt.Sprintf(GroupIDShardClientPrefix.String(), getNetworkPrefix(shardID), strconv.Itoa(int(shardID))))
} }
// ActionType lists action on group // ActionType lists action on group
@ -88,12 +102,3 @@ type GroupAction struct {
func (g GroupAction) String() string { func (g GroupAction) String() string {
return fmt.Sprintf("%s/%s", g.Name, g.Action) return fmt.Sprintf("%s/%s", g.Name, g.Action)
} }
// GroupReceiver is a multicast group message receiver interface.
type GroupReceiver interface {
// Close closes this receiver.
io.Closer
// Receive a message.
Receive(ctx context.Context) (msg []byte, sender libp2p_peer.ID, err error)
}

@ -1,4 +1,4 @@
package p2p package nodeconfig
import "testing" import "testing"

@ -9,7 +9,6 @@ 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/harmony/accounts" "github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core"
@ -18,6 +17,7 @@ import (
"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/params"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
) )
// Backend interface provides the common API services (that are provided by // Backend interface provides the common API services (that are provided by
@ -72,6 +72,7 @@ type Backend interface {
// retrieve the blockHash using txID and add blockHash to CxPool for resending // retrieve the blockHash using txID and add blockHash to CxPool for resending
ResendCx(ctx context.Context, txID common.Hash) (uint64, bool) ResendCx(ctx context.Context, txID common.Hash) (uint64, bool)
IsLeader() bool IsLeader() bool
SendStakingTx(ctx context.Context, newStakingTx *staking.StakingTransaction) error
} }
// GetAPIs returns all the APIs. // GetAPIs returns all the APIs.

@ -58,7 +58,7 @@ func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.
func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) { func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.GetBlock(ctx, blockHash) block, err := s.b.GetBlock(ctx, blockHash)
if block != nil { if block != nil {
return RPCMarshalBlock(block, false, false) return RPCMarshalBlock(block, true, fullTx)
} }
return nil, err return nil, err
} }

@ -2,7 +2,6 @@ package hmyapi
import ( import (
"context" "context"
"errors"
"strings" "strings"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -10,16 +9,20 @@ 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"
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"
"github.com/pkg/errors"
) )
// TxHistoryArgs is struct to make GetTransactionsHistory request // TxHistoryArgs is struct to make GetTransactionsHistory request
type TxHistoryArgs struct { type TxHistoryArgs struct {
Address string `json:"address"` Address string `json:"address"`
Offset int `json:"offset"` PageIndex int `json:"pageIndex"`
Page int `json:"page"` PageSize int `json:"pageSize"`
FullTx bool `json:"fullTx"`
} }
// PublicTransactionPoolAPI exposes methods for the RPC interface // PublicTransactionPoolAPI exposes methods for the RPC interface
@ -34,25 +37,35 @@ func NewPublicTransactionPoolAPI(b Backend, nonceLock *AddrLocker) *PublicTransa
} }
// GetTransactionsHistory returns the list of transactions hashes that involve a particular address. // GetTransactionsHistory returns the list of transactions hashes that involve a particular address.
func (s *PublicTransactionPoolAPI) GetTransactionsHistory(ctx context.Context, args TxHistoryArgs) ([]common.Hash, error) { func (s *PublicTransactionPoolAPI) GetTransactionsHistory(ctx context.Context, args TxHistoryArgs) (map[string]interface{}, error) {
address := args.Address address := args.Address
result := []common.Hash{}
if strings.HasPrefix(address, "one1") { if strings.HasPrefix(address, "one1") {
result, err := s.b.GetTransactionsHistory(address) hashes, err := s.b.GetTransactionsHistory(address)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return ReturnWithPagination(result, args), nil result = ReturnWithPagination(hashes, args)
} }
addr := internal_common.ParseAddr(address) addr := internal_common.ParseAddr(address)
oneAddress, err := internal_common.AddressToBech32(addr) oneAddress, err := internal_common.AddressToBech32(addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
result, err := s.b.GetTransactionsHistory(oneAddress) hashes, err := s.b.GetTransactionsHistory(oneAddress)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return ReturnWithPagination(result, args), nil result = ReturnWithPagination(hashes, args)
if !args.FullTx {
return map[string]interface{}{"transactions": result}, nil
}
txs := []*RPCTransaction{}
for _, hash := range result {
tx := s.GetTransactionByHash(ctx, hash)
txs = append(txs, tx)
}
return map[string]interface{}{"transactions": txs}, nil
} }
// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number. // GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
@ -155,6 +168,23 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
return SubmitTransaction(ctx, s.b, signed) return SubmitTransaction(ctx, s.b, signed)
} }
// SendRawStakingTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawStakingTransaction(
ctx context.Context, encodedTx hexutil.Bytes,
) (common.Hash, error) {
tx := new(staking.StakingTransaction)
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return common.Hash{}, err
}
c := s.b.ChainConfig().ChainID
if tx.ChainID().Cmp(c) != 0 {
e := errors.Wrapf(core.ErrInvalidChainID, "current chain id:%s", c.String())
return common.Hash{}, e
}
return SubmitStakingTransaction(ctx, s.b, tx)
}
// SendRawTransaction will add the signed transaction to the transaction pool. // SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce. // The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) { func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {
@ -162,8 +192,10 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod
if err := rlp.DecodeBytes(encodedTx, tx); err != nil { if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
if tx.ChainID().Cmp(s.b.ChainConfig().ChainID) != 0 { c := s.b.ChainConfig().ChainID
return common.Hash{}, errors.New("Incorrect chain ID. The current chain id: " + s.b.ChainConfig().ChainID.String()) if tx.ChainID().Cmp(c) != 0 {
e := errors.Wrapf(core.ErrInvalidChainID, "current chain id:%s", c.String())
return common.Hash{}, e
} }
return SubmitTransaction(ctx, s.b, tx) return SubmitTransaction(ctx, s.b, tx)
} }
@ -187,15 +219,11 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
if tx.Protected() { if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainID()) signer = types.NewEIP155Signer(tx.ChainID())
} }
from, _ := types.Sender(signer, tx)
fields := map[string]interface{}{ fields := map[string]interface{}{
"blockHash": blockHash, "blockHash": blockHash,
"blockNumber": hexutil.Uint64(blockNumber), "blockNumber": hexutil.Uint64(blockNumber),
"transactionHash": hash, "transactionHash": hash,
"transactionIndex": hexutil.Uint64(index), "transactionIndex": hexutil.Uint64(index),
"from": from,
"to": tx.To(),
"shardID": tx.ShardID(), "shardID": tx.ShardID(),
"gasUsed": hexutil.Uint64(receipt.GasUsed), "gasUsed": hexutil.Uint64(receipt.GasUsed),
"cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed), "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
@ -203,7 +231,19 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
"logs": receipt.Logs, "logs": receipt.Logs,
"logsBloom": receipt.Bloom, "logsBloom": receipt.Bloom,
} }
from, _ := types.Sender(signer, tx)
fields["from"] = from
fields["to"] = ""
if tx.To() != nil {
fields["to"], err = internal_common.AddressToBech32(*tx.To())
if err != nil {
return nil, err
}
fields["from"], err = internal_common.AddressToBech32(from)
if err != nil {
return nil, err
}
}
// Assign receipt status or post state. // Assign receipt status or post state.
if len(receipt.PostState) > 0 { if len(receipt.PostState) > 0 {
fields["root"] = hexutil.Bytes(receipt.PostState) fields["root"] = hexutil.Bytes(receipt.PostState)

@ -3,6 +3,7 @@ package hmyapi
import ( import (
"encoding/hex" "encoding/hex"
"math/big" "math/big"
"strings"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -10,7 +11,7 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/harmony-one/harmony/block" "github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
common2 "github.com/harmony-one/harmony/internal/common" internal_common "github.com/harmony-one/harmony/internal/common"
) )
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction // RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
@ -78,7 +79,7 @@ func newHeaderInformation(header *block.Header) *HeaderInformation {
sig := header.LastCommitSignature() sig := header.LastCommitSignature()
result.LastCommitSig = hex.EncodeToString(sig[:]) result.LastCommitSig = hex.EncodeToString(sig[:])
bechAddr, err := common2.AddressToBech32(header.Coinbase()) bechAddr, err := internal_common.AddressToBech32(header.Coinbase())
if err != nil { if err != nil {
bechAddr = header.Coinbase().Hex() bechAddr = header.Coinbase().Hex()
} }
@ -101,13 +102,15 @@ func newRPCCXReceipt(cx *types.CXReceipt, blockHash common.Hash, blockNumber uin
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber)) result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
} }
fromAddr, err := common2.AddressToBech32(cx.From) fromAddr, err := internal_common.AddressToBech32(cx.From)
if err != nil { if err != nil {
fromAddr = cx.From.Hex() return nil
} }
toAddr, err := common2.AddressToBech32(*cx.To) toAddr := ""
if err != nil { if cx.To != nil {
toAddr = (*cx.To).Hex() if toAddr, err = internal_common.AddressToBech32(*cx.To); err != nil {
return nil
}
} }
result.From = fromAddr result.From = fromAddr
result.To = toAddr result.To = toAddr
@ -144,15 +147,20 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
result.TransactionIndex = hexutil.Uint(index) result.TransactionIndex = hexutil.Uint(index)
} }
fromAddr, err := common2.AddressToBech32(from) fromAddr, err := internal_common.AddressToBech32(from)
if err != nil { if err != nil {
fromAddr = from.Hex() return nil
} }
toAddr, err := common2.AddressToBech32(*tx.To()) toAddr := ""
if err != nil {
toAddr = (*tx.To()).Hex() if tx.To() != nil {
if toAddr, err = internal_common.AddressToBech32(*tx.To()); err != nil {
return nil
}
result.From = fromAddr
} else {
result.From = strings.ToLower(from.Hex())
} }
result.From = fromAddr
result.To = toAddr result.To = toAddr
return result return result

@ -5,32 +5,37 @@ 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/types" "github.com/harmony-one/harmony/core/types"
common2 "github.com/harmony-one/harmony/internal/common" common2 "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
staking "github.com/harmony-one/harmony/staking/types"
) )
// defaultOffset is to have default pagination. // defaultPageSize is to have default pagination.
const ( const (
defaultOffset = 100 defaultPageSize = 100
) )
// ReturnWithPagination returns result with pagination (offset, page in TxHistoryArgs). // ReturnWithPagination returns result with pagination (offset, page in TxHistoryArgs).
func ReturnWithPagination(hashes []common.Hash, args TxHistoryArgs) []common.Hash { func ReturnWithPagination(hashes []common.Hash, args TxHistoryArgs) []common.Hash {
offset := defaultOffset pageSize := defaultPageSize
page := args.Page pageIndex := args.PageIndex
if args.Offset > 0 { if args.PageSize > 0 {
offset = args.Offset pageSize = args.PageSize
}
if pageSize*pageIndex >= len(hashes) {
return make([]common.Hash, 0)
} }
if offset*page+offset > len(hashes) { if pageSize*pageIndex+pageSize > len(hashes) {
return hashes[offset*page:] return hashes[pageSize*pageIndex:]
} }
return hashes[offset*page : offset*page+offset] return hashes[pageSize*pageIndex : pageSize*pageIndex+pageSize]
} }
// SubmitTransaction is a helper function that submits tx to txPool and logs a message. // SubmitTransaction is a helper function that submits tx to txPool and logs a message.
func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) { func SubmitTransaction(
ctx context.Context, b Backend, tx *types.Transaction,
) (common.Hash, error) {
if err := b.SendTx(ctx, tx); err != nil { if err := b.SendTx(ctx, tx); err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -53,3 +58,14 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
} }
return tx.Hash(), nil return tx.Hash(), nil
} }
// SubmitStakingTransaction is a helper function that submits tx to txPool and logs a message.
func SubmitStakingTransaction(
ctx context.Context, b Backend, tx *staking.StakingTransaction,
) (common.Hash, error) {
if err := b.SendStakingTx(ctx, tx); err != nil {
return common.Hash{}, err
}
utils.Logger().Info().Str("fullhash", tx.Hash().Hex()).Msg("Submitted Staking transaction")
return tx.Hash(), nil
}

@ -6,11 +6,7 @@ import (
"sync" "sync"
"time" "time"
types2 "github.com/harmony-one/harmony/staking/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/accounts" "github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/api/client" "github.com/harmony-one/harmony/api/client"
clientService "github.com/harmony-one/harmony/api/client/service" clientService "github.com/harmony-one/harmony/api/client/service"
@ -28,12 +24,14 @@ import (
"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"
"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/shardchain" "github.com/harmony-one/harmony/internal/shardchain"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/node/worker" "github.com/harmony-one/harmony/node/worker"
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
p2p_host "github.com/harmony-one/harmony/p2p/host" p2p_host "github.com/harmony-one/harmony/p2p/host"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
) )
// State is a state of a node. // State is a state of a node.
@ -127,7 +125,7 @@ type Node struct {
pendingTxMutex sync.Mutex pendingTxMutex sync.Mutex
recentTxsStats types.RecentTxsStats recentTxsStats types.RecentTxsStats
pendingStakingTransactions map[common.Hash]*types2.StakingTransaction // All the staking transactions received but not yet processed for Consensus pendingStakingTransactions map[common.Hash]*staking.StakingTransaction // All the staking transactions received but not yet processed for Consensus
pendingStakingTxMutex sync.Mutex pendingStakingTxMutex sync.Mutex
Worker *worker.Worker Worker *worker.Worker
@ -246,11 +244,11 @@ func (node *Node) Beaconchain() *core.BlockChain {
func (node *Node) tryBroadcast(tx *types.Transaction) { func (node *Node) tryBroadcast(tx *types.Transaction) {
msg := proto_node.ConstructTransactionListMessageAccount(types.Transactions{tx}) msg := proto_node.ConstructTransactionListMessageAccount(types.Transactions{tx})
shardGroupID := p2p.NewGroupIDByShardID(p2p.ShardID(tx.ShardID())) shardGroupID := nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(tx.ShardID()))
utils.Logger().Info().Str("shardGroupID", string(shardGroupID)).Msg("tryBroadcast") utils.Logger().Info().Str("shardGroupID", string(shardGroupID)).Msg("tryBroadcast")
for attempt := 0; attempt < NumTryBroadCast; attempt++ { for attempt := 0; attempt < NumTryBroadCast; attempt++ {
if err := node.host.SendMessageToGroups([]p2p.GroupID{shardGroupID}, p2p_host.ConstructP2pMessage(byte(0), msg)); err != nil && attempt < NumTryBroadCast { if err := node.host.SendMessageToGroups([]nodeconfig.GroupID{shardGroupID}, p2p_host.ConstructP2pMessage(byte(0), msg)); err != nil && attempt < NumTryBroadCast {
utils.Logger().Error().Int("attempt", attempt).Msg("Error when trying to broadcast tx") utils.Logger().Error().Int("attempt", attempt).Msg("Error when trying to broadcast tx")
} else { } else {
break break
@ -275,7 +273,7 @@ func (node *Node) addPendingTransactions(newTxs types.Transactions) {
} }
// Add new staking transactions to the pending staking transaction list. // Add new staking transactions to the pending staking transaction list.
func (node *Node) addPendingStakingTransactions(newStakingTxs types2.StakingTransactions) { func (node *Node) addPendingStakingTransactions(newStakingTxs staking.StakingTransactions) {
txPoolLimit := core.ShardingSchedule.MaxTxPoolSizeLimit() txPoolLimit := core.ShardingSchedule.MaxTxPoolSizeLimit()
node.pendingStakingTxMutex.Lock() node.pendingStakingTxMutex.Lock()
for _, tx := range newStakingTxs { for _, tx := range newStakingTxs {
@ -290,6 +288,12 @@ func (node *Node) addPendingStakingTransactions(newStakingTxs types2.StakingTran
utils.Logger().Info().Int("length of newStakingTxs", len(newStakingTxs)).Int("totalPending", len(node.pendingTransactions)).Msg("Got more staking transactions") utils.Logger().Info().Int("length of newStakingTxs", len(newStakingTxs)).Int("totalPending", len(node.pendingTransactions)).Msg("Got more staking transactions")
} }
// AddPendingStakingTransaction staking transactions
func (node *Node) AddPendingStakingTransaction(
newStakingTx *staking.StakingTransaction) {
node.addPendingStakingTransactions(staking.StakingTransactions{newStakingTx})
}
// AddPendingTransaction adds one new transaction to the pending transaction list. // AddPendingTransaction adds one new transaction to the pending transaction list.
// This is only called from SDK. // This is only called from SDK.
func (node *Node) AddPendingTransaction(newTx *types.Transaction) { func (node *Node) AddPendingTransaction(newTx *types.Transaction) {
@ -326,7 +330,9 @@ func (node *Node) AddPendingReceipts(receipts *types.CXReceiptsProof) {
// Take out a subset of valid transactions from the pending transaction list // Take out a subset of valid transactions from the pending transaction list
// Note the pending transaction list will then contain the rest of the txs // Note the pending transaction list will then contain the rest of the txs
func (node *Node) getTransactionsForNewBlock(coinbase common.Address) (types.Transactions, types2.StakingTransactions) { func (node *Node) getTransactionsForNewBlock(
coinbase common.Address,
) (types.Transactions, staking.StakingTransactions) {
txsThrottleConfig := core.ShardingSchedule.TxsThrottleConfig() txsThrottleConfig := core.ShardingSchedule.TxsThrottleConfig()
@ -347,7 +353,7 @@ func (node *Node) getTransactionsForNewBlock(coinbase common.Address) (types.Tra
utils.Logger().Error(). utils.Logger().Error().
Err(err). Err(err).
Msg("Failed updating worker's state before txn selection") Msg("Failed updating worker's state before txn selection")
return types.Transactions{}, types2.StakingTransactions{} return types.Transactions{}, staking.StakingTransactions{}
} }
node.pendingTxMutex.Lock() node.pendingTxMutex.Lock()
@ -356,7 +362,7 @@ func (node *Node) getTransactionsForNewBlock(coinbase common.Address) (types.Tra
defer node.pendingStakingTxMutex.Unlock() defer node.pendingStakingTxMutex.Unlock()
pendingTransactions := types.Transactions{} pendingTransactions := types.Transactions{}
pendingStakingTransactions := types2.StakingTransactions{} pendingStakingTransactions := staking.StakingTransactions{}
for _, tx := range node.pendingTransactions { for _, tx := range node.pendingTransactions {
pendingTransactions = append(pendingTransactions, tx) pendingTransactions = append(pendingTransactions, tx)
@ -378,7 +384,7 @@ func (node *Node) getTransactionsForNewBlock(coinbase common.Address) (types.Tra
Int("invalidDiscarded", len(invalid)). Int("invalidDiscarded", len(invalid)).
Msg("Selecting Transactions") Msg("Selecting Transactions")
node.pendingStakingTransactions = make(map[common.Hash]*types2.StakingTransaction) node.pendingStakingTransactions = make(map[common.Hash]*staking.StakingTransaction)
for _, unselectedStakingTx := range unselectedStaking { for _, unselectedStakingTx := range unselectedStaking {
node.pendingStakingTransactions[unselectedStakingTx.Hash()] = unselectedStakingTx node.pendingStakingTransactions[unselectedStakingTx.Hash()] = unselectedStakingTx
} }
@ -465,7 +471,7 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, chainDBFactory shardc
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]*types2.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
@ -604,15 +610,15 @@ func (node *Node) initNodeConfiguration() (service.NodeConfig, chan p2p.Peer) {
PushgatewayIP: node.NodeConfig.GetPushgatewayIP(), PushgatewayIP: node.NodeConfig.GetPushgatewayIP(),
PushgatewayPort: node.NodeConfig.GetPushgatewayPort(), PushgatewayPort: node.NodeConfig.GetPushgatewayPort(),
IsClient: node.NodeConfig.IsClient(), IsClient: node.NodeConfig.IsClient(),
Beacon: p2p.GroupIDBeacon, Beacon: nodeconfig.NewGroupIDByShardID(0),
ShardGroupID: node.NodeConfig.GetShardGroupID(), ShardGroupID: node.NodeConfig.GetShardGroupID(),
Actions: make(map[p2p.GroupID]p2p.ActionType), Actions: make(map[nodeconfig.GroupID]nodeconfig.ActionType),
} }
if nodeConfig.IsClient { if nodeConfig.IsClient {
nodeConfig.Actions[p2p.GroupIDBeaconClient] = p2p.ActionStart nodeConfig.Actions[nodeconfig.NewClientGroupIDByShardID(0)] = nodeconfig.ActionStart
} else { } else {
nodeConfig.Actions[node.NodeConfig.GetShardGroupID()] = p2p.ActionStart nodeConfig.Actions[node.NodeConfig.GetShardGroupID()] = nodeconfig.ActionStart
} }
var err error var err error
@ -621,7 +627,7 @@ func (node *Node) initNodeConfiguration() (service.NodeConfig, chan p2p.Peer) {
utils.Logger().Error().Err(err).Msg("Failed to create shard receiver") utils.Logger().Error().Err(err).Msg("Failed to create shard receiver")
} }
node.globalGroupReceiver, err = node.host.GroupReceiver(p2p.GroupIDBeaconClient) node.globalGroupReceiver, err = node.host.GroupReceiver(nodeconfig.NewClientGroupIDByShardID(0))
if err != nil { if err != nil {
utils.Logger().Error().Err(err).Msg("Failed to create global receiver") utils.Logger().Error().Err(err).Msg("Failed to create global receiver")
} }

@ -4,7 +4,6 @@ import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/p2p/host" "github.com/harmony-one/harmony/p2p/host"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -17,6 +16,7 @@ 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"
bls_cosi "github.com/harmony-one/harmony/crypto/bls" bls_cosi "github.com/harmony-one/harmony/crypto/bls"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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"
) )
@ -68,8 +68,8 @@ func (node *Node) BroadcastCXReceiptsWithShardID(block *types.Block, commitSig [
} }
utils.Logger().Info().Uint32("ToShardID", toShardID).Msg("[BroadcastCXReceiptsWithShardID] ReadCXReceipts and MerkleProof Found") utils.Logger().Info().Uint32("ToShardID", toShardID).Msg("[BroadcastCXReceiptsWithShardID] ReadCXReceipts and MerkleProof Found")
groupID := p2p.ShardID(toShardID) groupID := nodeconfig.ShardID(toShardID)
go node.host.SendMessageToGroups([]p2p.GroupID{p2p.NewGroupIDByShardID(groupID)}, host.ConstructP2pMessage(byte(0), proto_node.ConstructCXReceiptsProof(cxReceipts, merkleProof, block.Header(), commitSig, commitBitmap))) go node.host.SendMessageToGroups([]nodeconfig.GroupID{nodeconfig.NewGroupIDByShardID(groupID)}, host.ConstructP2pMessage(byte(0), proto_node.ConstructCXReceiptsProof(cxReceipts, merkleProof, block.Header(), commitSig, commitBitmap)))
} }
// BroadcastMissingCXReceipts broadcasts missing cross shard receipts per request // BroadcastMissingCXReceipts broadcasts missing cross shard receipts per request

@ -9,16 +9,11 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
types2 "github.com/harmony-one/harmony/staking/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
pb "github.com/golang/protobuf/proto" pb "github.com/golang/protobuf/proto"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
libp2p_peer "github.com/libp2p/go-libp2p-peer"
"github.com/harmony-one/harmony/api/proto" "github.com/harmony-one/harmony/api/proto"
proto_discovery "github.com/harmony-one/harmony/api/proto/discovery" proto_discovery "github.com/harmony-one/harmony/api/proto/discovery"
"github.com/harmony-one/harmony/api/proto/message" "github.com/harmony-one/harmony/api/proto/message"
@ -32,6 +27,8 @@ import (
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/p2p/host" "github.com/harmony-one/harmony/p2p/host"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
staking "github.com/harmony-one/harmony/staking/types"
libp2p_peer "github.com/libp2p/go-libp2p-peer"
) )
const ( const (
@ -244,7 +241,7 @@ func (node *Node) transactionMessageHandler(msgPayload []byte) {
} }
func (node *Node) stakingMessageHandler(msgPayload []byte) { func (node *Node) stakingMessageHandler(msgPayload []byte) {
txs := types2.StakingTransactions{} txs := staking.StakingTransactions{}
err := rlp.Decode(bytes.NewReader(msgPayload[:]), &txs) err := rlp.Decode(bytes.NewReader(msgPayload[:]), &txs)
if err != nil { if err != nil {
utils.Logger().Error(). utils.Logger().Error().
@ -259,7 +256,7 @@ func (node *Node) stakingMessageHandler(msgPayload []byte) {
// NOTE: For now, just send to the client (basically not broadcasting) // NOTE: For now, just send to the client (basically not broadcasting)
// TODO (lc): broadcast the new blocks to new nodes doing state sync // TODO (lc): broadcast the new blocks to new nodes doing state sync
func (node *Node) BroadcastNewBlock(newBlock *types.Block) { func (node *Node) BroadcastNewBlock(newBlock *types.Block) {
groups := []p2p.GroupID{node.NodeConfig.GetClientGroupID()} groups := []nodeconfig.GroupID{node.NodeConfig.GetClientGroupID()}
utils.Logger().Info().Msgf("broadcasting new block %d, group %s", newBlock.NumberU64(), groups[0]) utils.Logger().Info().Msgf("broadcasting new block %d, group %s", newBlock.NumberU64(), groups[0])
msg := host.ConstructP2pMessage(byte(0), proto_node.ConstructBlocksSyncMessage([]*types.Block{newBlock})) msg := host.ConstructP2pMessage(byte(0), proto_node.ConstructBlocksSyncMessage([]*types.Block{newBlock}))
if err := node.host.SendMessageToGroups(groups, msg); err != nil { if err := node.host.SendMessageToGroups(groups, msg); err != nil {
@ -303,7 +300,7 @@ func (node *Node) BroadcastCrossLinkHeader(newBlock *types.Block) {
for _, header := range headers { for _, header := range headers {
utils.Logger().Debug().Msgf("[BroadcastCrossLinkHeader] Broadcasting %d", header.Number().Uint64()) utils.Logger().Debug().Msgf("[BroadcastCrossLinkHeader] Broadcasting %d", header.Number().Uint64())
} }
node.host.SendMessageToGroups([]p2p.GroupID{node.NodeConfig.GetBeaconGroupID()}, host.ConstructP2pMessage(byte(0), proto_node.ConstructCrossLinkHeadersMessage(headers))) node.host.SendMessageToGroups([]nodeconfig.GroupID{node.NodeConfig.GetBeaconGroupID()}, host.ConstructP2pMessage(byte(0), proto_node.ConstructCrossLinkHeadersMessage(headers)))
} }
// VerifyNewBlock is called by consensus participants to verify the block (account model) they are running consensus on // VerifyNewBlock is called by consensus participants to verify the block (account model) they are running consensus on

@ -6,7 +6,6 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"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/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"

@ -20,9 +20,9 @@ import (
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"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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/p2p"
"github.com/harmony-one/harmony/p2p/host" "github.com/harmony-one/harmony/p2p/host"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
) )
@ -141,7 +141,7 @@ func (node *Node) broadcastEpochShardState(newBlock *types.Block) error {
}, },
) )
return node.host.SendMessageToGroups( return node.host.SendMessageToGroups(
[]p2p.GroupID{node.NodeConfig.GetClientGroupID()}, []nodeconfig.GroupID{node.NodeConfig.GetClientGroupID()},
host.ConstructP2pMessage(byte(0), epochShardStateMessage)) host.ConstructP2pMessage(byte(0), epochShardStateMessage))
} }

@ -14,7 +14,6 @@ import (
"github.com/harmony-one/harmony/api/service/networkinfo" "github.com/harmony-one/harmony/api/service/networkinfo"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node" nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p"
) )
func (node *Node) setupForValidator() { func (node *Node) setupForValidator() {
@ -59,7 +58,7 @@ func (node *Node) setupForNewNode() {
func (node *Node) setupForClientNode() { func (node *Node) setupForClientNode() {
// Register networkinfo service. "0" is the beacon shard ID // Register networkinfo service. "0" is the beacon shard ID
node.serviceManager.RegisterService(service.NetworkInfo, networkinfo.MustNew(node.host, p2p.GroupIDBeacon, nil, nil, node.networkInfoDHTPath())) node.serviceManager.RegisterService(service.NetworkInfo, networkinfo.MustNew(node.host, nodeconfig.NewGroupIDByShardID(0), nil, nil, node.networkInfoDHTPath()))
} }
func (node *Node) setupForExplorerNode() { func (node *Node) setupForExplorerNode() {
@ -109,8 +108,8 @@ func (node *Node) StopServices() {
func (node *Node) networkInfoDHTPath() string { func (node *Node) networkInfoDHTPath() string {
return fmt.Sprintf(".dht-%s-%s-c%s", return fmt.Sprintf(".dht-%s-%s-c%s",
node.NodeConfig.SelfPeer.IP, node.SelfPeer.IP,
node.NodeConfig.SelfPeer.Port, node.SelfPeer.Port,
node.chainConfig.ChainID, node.chainConfig.ChainID,
) )
} }

@ -5,27 +5,21 @@ import (
"math/big" "math/big"
"time" "time"
types2 "github.com/harmony-one/harmony/staking/types"
blockfactory "github.com/harmony-one/harmony/block/factory"
"github.com/harmony-one/harmony/shard"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"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" "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/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"
"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"
staking "github.com/harmony-one/harmony/staking/types"
) )
// environment is the worker's current environment and holds all of the current state information. // environment is the worker's current environment and holds all of the current state information.
@ -150,9 +144,14 @@ 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(newBlockNum uint64, txs types2.StakingTransactions, recentTxsStats types.RecentTxsStats, txsThrottleConfig *shardingconfig.TxsThrottleConfig, coinbase common.Address) (types2.StakingTransactions, types2.StakingTransactions, types2.StakingTransactions) { func (w *Worker) SelectStakingTransactionsForNewBlock(
newBlockNum uint64, txs staking.StakingTransactions,
recentTxsStats types.RecentTxsStats,
txsThrottleConfig *shardingconfig.TxsThrottleConfig,
coinbase common.Address) (staking.StakingTransactions, staking.StakingTransactions, staking.StakingTransactions) {
// TODO: implement staking transaction selection // TODO: implement staking transaction selection
return types2.StakingTransactions{}, types2.StakingTransactions{}, types2.StakingTransactions{} t := staking.StakingTransactions{}
return t, t, t
} }
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) {
@ -179,7 +178,8 @@ func (w *Worker) commitTransaction(tx *types.Transaction, coinbase common.Addres
} }
// CommitTransactions commits transactions including staking transactions. // CommitTransactions commits transactions including staking transactions.
func (w *Worker) CommitTransactions(txs types.Transactions, stakingTxns types2.StakingTransactions, coinbase common.Address) error { func (w *Worker) CommitTransactions(
txs types.Transactions, stakingTxns staking.StakingTransactions, coinbase common.Address) error {
// Must update to the correct current state before processing potential txns // Must update to the correct current state before processing potential txns
if err := w.UpdateCurrent(coinbase); err != nil { if err := w.UpdateCurrent(coinbase); err != nil {
utils.Logger().Error(). utils.Logger().Error().

@ -5,18 +5,16 @@ import (
"math/rand" "math/rand"
"testing" "testing"
types2 "github.com/harmony-one/harmony/staking/types"
blockfactory "github.com/harmony-one/harmony/block/factory"
chain2 "github.com/harmony-one/harmony/internal/chain"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"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/common/denominations" "github.com/harmony-one/harmony/common/denominations"
"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"
chain2 "github.com/harmony-one/harmony/internal/chain"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
staking "github.com/harmony-one/harmony/staking/types"
) )
var ( var (
@ -77,7 +75,7 @@ func TestCommitTransactions(t *testing.T) {
tx, _ := types.SignTx(types.NewTransaction(baseNonce, testBankAddress, uint32(0), big.NewInt(int64(denominations.One*randAmount)), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey) tx, _ := types.SignTx(types.NewTransaction(baseNonce, testBankAddress, uint32(0), big.NewInt(int64(denominations.One*randAmount)), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey)
// Commit the tx to the worker // Commit the tx to the worker
err := worker.CommitTransactions(types.Transactions{tx}, types2.StakingTransactions{}, testBankAddress) err := worker.CommitTransactions(types.Transactions{tx}, staking.StakingTransactions{}, testBankAddress)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

@ -1,6 +1,7 @@
package p2p package p2p
import ( import (
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
libp2p_host "github.com/libp2p/go-libp2p-host" libp2p_host "github.com/libp2p/go-libp2p-host"
libp2p_peer "github.com/libp2p/go-libp2p-peer" libp2p_peer "github.com/libp2p/go-libp2p-peer"
) )
@ -21,11 +22,11 @@ type Host interface {
ConnectHostPeer(Peer) ConnectHostPeer(Peer)
// SendMessageToGroups sends a message to one or more multicast groups. // SendMessageToGroups sends a message to one or more multicast groups.
SendMessageToGroups(groups []GroupID, msg []byte) error SendMessageToGroups(groups []nodeconfig.GroupID, msg []byte) error
// GroupReceiver returns a receiver of messages sent to a multicast group. // GroupReceiver returns a receiver of messages sent to a multicast group.
// Each call creates a new receiver. // Each call creates a new receiver.
// If multiple receivers are created for the same group, // If multiple receivers are created for the same group,
// a message sent to the group will be delivered to all of the receivers. // a message sent to the group will be delivered to all of the receivers.
GroupReceiver(GroupID) (receiver GroupReceiver, err error) GroupReceiver(nodeconfig.GroupID) (receiver GroupReceiver, err error)
} }

@ -9,6 +9,7 @@ import (
"github.com/rs/zerolog" "github.com/rs/zerolog"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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"
@ -54,7 +55,7 @@ type HostV2 struct {
} }
// SendMessageToGroups sends a message to one or more multicast groups. // SendMessageToGroups sends a message to one or more multicast groups.
func (host *HostV2) SendMessageToGroups(groups []p2p.GroupID, msg []byte) error { func (host *HostV2) SendMessageToGroups(groups []nodeconfig.GroupID, msg []byte) error {
var error error var error error
for _, group := range groups { for _, group := range groups {
err := host.pubsub.Publish(string(group), msg) err := host.pubsub.Publish(string(group), msg)
@ -100,7 +101,7 @@ func (r *GroupReceiverImpl) Receive(ctx context.Context) (
// GroupReceiver returns a receiver of messages sent to a multicast group. // GroupReceiver returns a receiver of messages sent to a multicast group.
// See the GroupReceiver interface for details. // See the GroupReceiver interface for details.
func (host *HostV2) GroupReceiver(group p2p.GroupID) ( func (host *HostV2) GroupReceiver(group nodeconfig.GroupID) (
receiver p2p.GroupReceiver, err error, receiver p2p.GroupReceiver, err error,
) { ) {
sub, err := host.pubsub.Subscribe(string(group)) sub, err := host.pubsub.Subscribe(string(group))

@ -11,7 +11,7 @@ import (
libp2p_pubsub "github.com/libp2p/go-libp2p-pubsub" libp2p_pubsub "github.com/libp2p/go-libp2p-pubsub"
libp2p_pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" libp2p_pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb"
"github.com/harmony-one/harmony/p2p" nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
mock "github.com/harmony-one/harmony/p2p/host/hostv2/mock" mock "github.com/harmony-one/harmony/p2p/host/hostv2/mock"
) )
@ -19,7 +19,7 @@ func TestHostV2_SendMessageToGroups(t *testing.T) {
t.Run("Basic", func(t *testing.T) { t.Run("Basic", func(t *testing.T) {
mc := gomock.NewController(t) mc := gomock.NewController(t)
defer mc.Finish() defer mc.Finish()
groups := []p2p.GroupID{"ABC", "DEF"} groups := []nodeconfig.GroupID{"ABC", "DEF"}
data := []byte{1, 2, 3} data := []byte{1, 2, 3}
pubsub := mock.NewMockpubsub(mc) pubsub := mock.NewMockpubsub(mc)
gomock.InOrder( gomock.InOrder(
@ -34,7 +34,7 @@ func TestHostV2_SendMessageToGroups(t *testing.T) {
t.Run("Error", func(t *testing.T) { t.Run("Error", func(t *testing.T) {
mc := gomock.NewController(t) mc := gomock.NewController(t)
defer mc.Finish() defer mc.Finish()
groups := []p2p.GroupID{"ABC", "DEF"} groups := []nodeconfig.GroupID{"ABC", "DEF"}
data := []byte{1, 2, 3} data := []byte{1, 2, 3}
pubsub := mock.NewMockpubsub(mc) pubsub := mock.NewMockpubsub(mc)
gomock.InOrder( gomock.InOrder(

@ -6,6 +6,7 @@ package mock_p2p
import ( import (
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
node "github.com/harmony-one/harmony/internal/configs/node"
p2p "github.com/harmony-one/harmony/p2p" p2p "github.com/harmony-one/harmony/p2p"
go_libp2p_host "github.com/libp2p/go-libp2p-host" go_libp2p_host "github.com/libp2p/go-libp2p-host"
go_libp2p_peer "github.com/libp2p/go-libp2p-peer" go_libp2p_peer "github.com/libp2p/go-libp2p-peer"
@ -132,7 +133,7 @@ func (mr *MockHostMockRecorder) ConnectHostPeer(arg0 interface{}) *gomock.Call {
} }
// SendMessageToGroups mocks base method // SendMessageToGroups mocks base method
func (m *MockHost) SendMessageToGroups(groups []p2p.GroupID, msg []byte) error { func (m *MockHost) SendMessageToGroups(groups []node.GroupID, msg []byte) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendMessageToGroups", groups, msg) ret := m.ctrl.Call(m, "SendMessageToGroups", groups, msg)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(error)
@ -146,7 +147,7 @@ func (mr *MockHostMockRecorder) SendMessageToGroups(groups, msg interface{}) *go
} }
// GroupReceiver mocks base method // GroupReceiver mocks base method
func (m *MockHost) GroupReceiver(arg0 p2p.GroupID) (p2p.GroupReceiver, error) { func (m *MockHost) GroupReceiver(arg0 node.GroupID) (p2p.GroupReceiver, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GroupReceiver", arg0) ret := m.ctrl.Call(m, "GroupReceiver", arg0)
ret0, _ := ret[0].(p2p.GroupReceiver) ret0, _ := ret[0].(p2p.GroupReceiver)

@ -1,7 +1,9 @@
package p2p package p2p
import ( import (
"context"
"fmt" "fmt"
"io"
"net" "net"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
@ -28,3 +30,12 @@ func (p Peer) String() string {
} }
return fmt.Sprintf("BlsPubKey:%s-%s/%s[%d]", BlsPubKey, net.JoinHostPort(p.IP, p.Port), p.PeerID, len(p.Addrs)) return fmt.Sprintf("BlsPubKey:%s-%s/%s[%d]", BlsPubKey, net.JoinHostPort(p.IP, p.Port), p.PeerID, len(p.Addrs))
} }
// GroupReceiver is a multicast group message receiver interface.
type GroupReceiver interface {
// Close closes this receiver.
io.Closer
// Receive a message.
Receive(ctx context.Context) (msg []byte, sender libp2p_peer.ID, err error)
}

@ -8,6 +8,7 @@ SRC[txgen]=cmd/client/txgen/main.go
SRC[bootnode]=cmd/bootnode/main.go SRC[bootnode]=cmd/bootnode/main.go
SRC[wallet]="cmd/client/wallet/main.go cmd/client/wallet/generated_wallet.ini.go" SRC[wallet]="cmd/client/wallet/main.go cmd/client/wallet/generated_wallet.ini.go"
SRC[wallet_stress_test]="cmd/client/wallet_stress_test/main.go cmd/client/wallet_stress_test/generated_wallet.ini.go" SRC[wallet_stress_test]="cmd/client/wallet_stress_test/main.go cmd/client/wallet_stress_test/generated_wallet.ini.go"
SRC[staking-standalone]='cmd/staking/*.go'
BINDIR=bin BINDIR=bin
BUCKET=unique-bucket-bin BUCKET=unique-bucket-bin
@ -106,10 +107,10 @@ function build_only
env GOOS=$GOOS GOARCH=$GOARCH go build $VERBOSE -gcflags="all=-c 2" -ldflags="-X main.version=v${VERSION} -X main.commit=${COMMIT} -X main.builtAt=${BUILTAT} -X main.builtBy=${BUILTBY}" -o $BINDIR/$bin $RACE ${SRC[$bin]} env GOOS=$GOOS GOARCH=$GOARCH go build $VERBOSE -gcflags="all=-c 2" -ldflags="-X main.version=v${VERSION} -X main.commit=${COMMIT} -X main.builtAt=${BUILTAT} -X main.builtBy=${BUILTBY}" -o $BINDIR/$bin $RACE ${SRC[$bin]}
fi fi
if [ "$(uname -s)" == "Linux" ]; then if [ "$(uname -s)" == "Linux" ]; then
$BINDIR/$bin -version $BINDIR/$bin -version || $BINDIR/$bin version
fi fi
if [ "$(uname -s)" == "Darwin" -a "$GOOS" == "darwin" -a -e $BINDIR/$bin ]; then if [ "$(uname -s)" == "Darwin" -a "$GOOS" == "darwin" -a -e $BINDIR/$bin ]; then
$BINDIR/$bin -version $BINDIR/$bin -version || $BINDIR/$bin version
fi fi
fi fi
done done
@ -256,6 +257,6 @@ case "$ACTION" in
"upload") upload ;; "upload") upload ;;
"release") release ;; "release") release ;;
"pubwallet") upload_wallet ;; "pubwallet") upload_wallet ;;
"harmony"|"wallet"|"txgen"|"bootnode") build_only $ACTION ;; "harmony"|"wallet"|"txgen"|"bootnode"|"staking-standalone") build_only $ACTION ;;
*) usage ;; *) usage ;;
esac esac

@ -8,7 +8,8 @@ type (
// Commission defines a commission parameters for a given validator. // Commission defines a commission parameters for a given validator.
Commission struct { Commission struct {
CommissionRates `json:"commission_rates" yaml:"commission_rates"` CommissionRates `json:"commission_rates" yaml:"commission_rates"`
UpdateHeight *big.Int `json:"update_time" yaml:"update_time"` // the block height the commission rate was last changed UpdateHeight *big.Int `json:"update_height" yaml:"update_height"` // the block height the commission rate was last changed
} }
// CommissionRates defines the initial commission rates to be used for creating a // CommissionRates defines the initial commission rates to be used for creating a
@ -19,3 +20,9 @@ type (
MaxChangeRate Dec `json:"max_change_rate" yaml:"max_change_rate"` // maximum increase of the validator commission every epoch, as a fraction MaxChangeRate 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}
}

@ -5,7 +5,6 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )

@ -0,0 +1,247 @@
package types
import (
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/internal/common"
)
// DVPair is struct that just has a delegator-validator pair with no other data.
// It is intended to be used as a marshalable pointer. For example, a DVPair can be used to construct the
// key to getting an UnbondingDelegation from state.
type DVPair struct {
DelegatorAddress common.Address
ValidatorAddress common.Address
}
// DVVTriplet is struct that just has a delegator-validator-validator triplet with no other data.
// It is intended to be used as a marshalable pointer. For example, a DVVTriplet can be used to construct the
// key to getting a Redelegation from state.
type DVVTriplet struct {
DelegatorAddress common.Address
ValidatorSrcAddress common.Address
ValidatorDstAddress common.Address
}
// Delegation represents the bond with tokens held by an account. It is
// owned by one delegator, and is associated with the voting power of one
// validator.
type Delegation struct {
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"`
ValidatorAddress common.Address `json:"validator_address" yaml:"validator_address"`
Amount *big.Int `json:"amount" yaml:"amount"`
}
// NewDelegation creates a new delegation object
func NewDelegation(delegatorAddr common.Address, validatorAddr common.Address,
amount *big.Int) Delegation {
return Delegation{
DelegatorAddress: delegatorAddr,
ValidatorAddress: validatorAddr,
Amount: amount,
}
}
// MarshalDelegation return the delegation
func MarshalDelegation(delegation Delegation) ([]byte, error) {
return rlp.EncodeToBytes(delegation)
}
// UnmarshalDelegation return the delegation
func UnmarshalDelegation(by []byte) (*Delegation, error) {
decoded := &Delegation{}
err := rlp.DecodeBytes(by, decoded)
return decoded, err
}
// GetDelegatorAddr returns DelegatorAddr
func (d Delegation) GetDelegatorAddr() common.Address { return d.DelegatorAddress }
// GetValidatorAddr returns ValidatorAddr
func (d Delegation) GetValidatorAddr() common.Address { return d.ValidatorAddress }
// GetAmount returns amount of a delegation
func (d Delegation) GetAmount() *big.Int { return d.Amount }
// String returns a human readable string representation of a Delegation.
func (d Delegation) String() string {
return fmt.Sprintf(`Delegation:
Delegator: %s
Validator: %s
Amount: %s`, d.DelegatorAddress,
d.ValidatorAddress, d.Amount)
}
// Delegations is a collection of delegations
type Delegations []Delegation
// String returns the string representation of a list of delegations
func (d Delegations) String() (out string) {
for _, del := range d {
out += del.String() + "\n"
}
return strings.TrimSpace(out)
}
// UnbondingDelegation stores all of a single delegator's unbonding bonds
// for a single validator in an time-ordered list
type UnbondingDelegation struct {
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` // delegator
ValidatorAddress common.Address `json:"validator_address" yaml:"validator_address"` // validator unbonding from operator addr
Entries []UnbondingDelegationEntry `json:"entries" yaml:"entries"` // unbonding delegation entries
}
// UnbondingDelegationEntry - entry to an UnbondingDelegation
type UnbondingDelegationEntry struct {
ExitEpoch *big.Int `json:"exit_epoch" yaml:"exit_epoch"` // epoch which the unbonding begins
Amount *big.Int `json:"amount" yaml:"amount"` // atoms to receive at completion
}
// NewUnbondingDelegation - create a new unbonding delegation object
func NewUnbondingDelegation(delegatorAddr common.Address,
validatorAddr common.Address, epoch *big.Int, amt *big.Int) UnbondingDelegation {
entry := NewUnbondingDelegationEntry(epoch, amt)
return UnbondingDelegation{
DelegatorAddress: delegatorAddr,
ValidatorAddress: validatorAddr,
Entries: []UnbondingDelegationEntry{entry},
}
}
// NewUnbondingDelegationEntry - create a new unbonding delegation object
func NewUnbondingDelegationEntry(epoch *big.Int, amt *big.Int) UnbondingDelegationEntry {
return UnbondingDelegationEntry{
ExitEpoch: epoch,
Amount: amt,
}
}
// AddEntry - append entry to the unbonding delegation
// if there exists same ExitEpoch entry, merge the amount
// TODO: check the total amount not exceed the staking amount call this function
func (d *UnbondingDelegation) AddEntry(epoch *big.Int, amt *big.Int) {
entry := NewUnbondingDelegationEntry(epoch, amt)
for i := range d.Entries {
if d.Entries[i].ExitEpoch == entry.ExitEpoch {
d.Entries[i].Amount.Add(d.Entries[i].Amount, entry.Amount)
return
}
}
// same exit epoch entry not found
d.Entries = append(d.Entries, entry)
return
}
// String returns a human readable string representation of an UnbondingDelegation.
func (d UnbondingDelegation) String() string {
out := fmt.Sprintf(`Unbonding Delegations between:
Delegator: %s
Validator: %s
Entries:`, d.DelegatorAddress, d.ValidatorAddress)
for i, entry := range d.Entries {
out += fmt.Sprintf(` Unbonding Delegation %d:
ExitEpoch: %v
Amount: %s`, i, entry.ExitEpoch, entry.Amount)
}
return out
}
// UnbondingDelegations is a collection of UnbondingDelegation
type UnbondingDelegations []UnbondingDelegation
func (ubds UnbondingDelegations) String() (out string) {
for _, u := range ubds {
out += u.String() + "\n"
}
return strings.TrimSpace(out)
}
// Redelegation contains the list of a particular delegator's
// redelegating bonds from a particular source validator to a
// particular destination validator
type Redelegation struct {
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` // delegator
ValidatorSrcAddress common.Address `json:"validator_src_address" yaml:"validator_src_address"` // validator redelegation source operator addr
ValidatorDstAddress common.Address `json:"validator_dst_address" yaml:"validator_dst_address"` // validator redelegation destination operator addr
Entries []RedelegationEntry `json:"entries" yaml:"entries"` // redelegation entries
}
// RedelegationEntry - entry to a Redelegation
type RedelegationEntry struct {
Epoch *big.Int `json:"epoch" yaml:"epoch"` // epoch at which the redelegation took place
Amount *big.Int `json:"amount" yaml:"amount"` // amount of destination-validator tokens created by redelegation
}
// NewRedelegation - create a new redelegation object
func NewRedelegation(delegatorAddr common.Address, validatorSrcAddr,
validatorDstAddr common.Address, epoch *big.Int, amt *big.Int) Redelegation {
entry := NewRedelegationEntry(epoch, amt)
return Redelegation{
DelegatorAddress: delegatorAddr,
ValidatorSrcAddress: validatorSrcAddr,
ValidatorDstAddress: validatorDstAddr,
Entries: []RedelegationEntry{entry},
}
}
// NewRedelegationEntry - create a new redelegation object
func NewRedelegationEntry(epoch *big.Int, amt *big.Int) RedelegationEntry {
return RedelegationEntry{
Epoch: epoch,
Amount: amt,
}
}
// AddEntry - append entry to the unbonding delegation
// Merge if has same epoch field
func (d *Redelegation) AddEntry(epoch *big.Int, amt *big.Int) {
entry := NewRedelegationEntry(epoch, amt)
for i := range d.Entries {
if d.Entries[i].Epoch == entry.Epoch {
d.Entries[i].Amount.Add(d.Entries[i].Amount, entry.Amount)
return
}
}
// same epoch entry not found
d.Entries = append(d.Entries, entry)
return
}
// String returns a human readable string representation of a Redelegation.
func (d Redelegation) String() string {
out := fmt.Sprintf(`Redelegations between:
Delegator: %s
Source Validator: %s
Destination Validator: %s
Entries:
`,
d.DelegatorAddress, d.ValidatorSrcAddress, d.ValidatorDstAddress,
)
for i, entry := range d.Entries {
out += fmt.Sprintf(` Redelegation Entry #%d:
Epoch: %v
Amount: %v
`,
i, entry.Epoch, entry.Amount,
)
}
return strings.TrimRight(out, "\n")
}
// Redelegations are a collection of Redelegation
type Redelegations []Redelegation
func (d Redelegations) String() (out string) {
for _, red := range d {
out += red.String() + "\n"
}
return strings.TrimSpace(out)
}

@ -1,231 +1,77 @@
package types package types
import ( import (
"encoding/json"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/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"
) )
// Directive says what kind of payload follows
type Directive byte
const ( const (
// CreateValidator ... // DirectiveNewValidator ...
CreateValidator = "create_validator" DirectiveNewValidator Directive = iota
// EditValidator ... // DirectiveEditValidator ...
EditValidator = "edit_validator" DirectiveEditValidator
// Delegate ... // DirectiveDelegate ...
Delegate = "delegate" DirectiveDelegate
// Redelegate ... // DirectiveRedelegate ...
Redelegate = "redelegate" DirectiveRedelegate
// Undelegate ... // DirectiveUndelegate ...
Undelegate = "undelegate" DirectiveUndelegate
) )
// StakingMessage must fulfill these interfaces var (
type StakingMessage interface { directiveKind = [...]string{
// Type returns a human-readable string for the type of the staking message "NewValidator", "EditValidator", "Delegate", "Redelegate", "Undelegate",
Type() string }
// ErrInvalidStakingKind given when caller gives bad staking message kind
// Signer returns the ECDSA address who must sign the outer transaction ErrInvalidStakingKind = errors.New("bad staking kind")
Signer() common.Address )
}
// MsgCreateValidator - struct for creating a new validator func (d Directive) String() string {
type MsgCreateValidator struct { return directiveKind[d]
Description Description `json:"description" yaml:"description"`
Commission CommissionRates `json:"commission" yaml:"commission"`
MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"`
StakingAddress common.Address `json:"staking_address" yaml:"staking_address"`
ValidatingPubKey shard.BlsPublicKey `json:"validating_pub_key" yaml:"validating_pub_key"`
Amount *big.Int `json:"amount" yaml:"amount"`
} }
// msgCreateValidatorJSON - struct for creating a new validator for JSON // NewValidator - type for creating a new validator
type msgCreateValidatorJSON struct { type NewValidator struct {
Description Description `json:"description" yaml:"description"` Description `json:"ties" yaml:"ties"`
Commission 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"`
ValidatingPubKey shard.BlsPublicKey `json:"validating_pub_key" yaml:"validating_pub_key"` PubKey shard.BlsPublicKey `json:"validating_pub_key" yaml:"validating_pub_key"`
Amount *big.Int `json:"amount" yaml:"amount"` Amount *big.Int `json:"amount" yaml:"amount"`
} }
// NewMsgCreateValidator creates a new validator // EditValidator - type for edit existing validator
func NewMsgCreateValidator( type EditValidator struct {
description Description, commission CommissionRates, minSelfDelegation *big.Int, stakingAddress common.Address, validatingPubKey shard.BlsPublicKey, amount *big.Int) MsgCreateValidator {
return MsgCreateValidator{
Description: description,
Commission: commission,
MinSelfDelegation: minSelfDelegation,
StakingAddress: stakingAddress,
ValidatingPubKey: validatingPubKey,
Amount: amount,
}
}
// Type ...
func (msg MsgCreateValidator) Type() string { return CreateValidator }
// Signer ...
func (msg MsgCreateValidator) Signer() common.Address { return msg.StakingAddress }
// MarshalJSON implements the json.Marshaler interface to provide custom JSON
// serialization of the MsgCreateValidator type.
func (msg MsgCreateValidator) MarshalJSON() ([]byte, error) {
return json.Marshal(msgCreateValidatorJSON{
Description: msg.Description,
Commission: msg.Commission,
MinSelfDelegation: msg.MinSelfDelegation,
StakingAddress: msg.StakingAddress,
ValidatingPubKey: msg.ValidatingPubKey,
Amount: msg.Amount,
})
}
// UnmarshalJSON implements the json.Unmarshaler interface to provide custom
// JSON deserialization of the MsgCreateValidator type.
func (msg *MsgCreateValidator) UnmarshalJSON(bz []byte) error {
var msgCreateValJSON msgCreateValidatorJSON
if err := json.Unmarshal(bz, &msgCreateValJSON); err != nil {
return err
}
msg.Description = msgCreateValJSON.Description
msg.Commission = msgCreateValJSON.Commission
msg.MinSelfDelegation = msgCreateValJSON.MinSelfDelegation
msg.StakingAddress = msgCreateValJSON.StakingAddress
msg.ValidatingPubKey = msgCreateValJSON.ValidatingPubKey
msg.Amount = msgCreateValJSON.Amount
return nil
}
// ValidateBasic quick validity check
func (msg MsgCreateValidator) ValidateBasic() error {
// note that unmarshaling from bech32 ensures either empty or valid
if msg.StakingAddress.Big().Uint64() == 0 {
return errors.New("[CreateValidator] address is empty")
}
if msg.ValidatingPubKey.IsEmpty() {
return errors.New("[CreateValidator] invalid BLS public key")
}
if msg.Description == (Description{}) {
return errors.New("[CreateValidator] description must be included")
}
if msg.Commission == (CommissionRates{}) {
return errors.New("[CreateValidator] commission must be included")
}
if msg.Amount.Cmp(msg.MinSelfDelegation) > 0 {
return errors.New("[CreateValidator] stake amount must be >= MinSelfDelegation")
}
return nil
}
// MsgEditValidator - struct for editing a validator
type MsgEditValidator 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 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"`
}
// MsgEditValidatorJSON - struct for editing a validator for JSON
type MsgEditValidatorJSON struct {
Description
StakingAddress common.Address `json:"staking_address" yaml:"staking_address"`
// TODO: allow update of bls public key
CommissionRate Dec `json:"commission_rate" yaml:"commission_rate"`
MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"`
}
// NewMsgEditValidator creates a new MsgEditValidator.
func NewMsgEditValidator(
description Description, stakingAddress common.Address, commissionRate Dec, minSelfDelegation *big.Int) MsgEditValidator {
return MsgEditValidator{
Description: description,
StakingAddress: stakingAddress,
CommissionRate: commissionRate,
MinSelfDelegation: minSelfDelegation,
}
} }
// Type ... // Delegate - type for delegating to a validator
func (msg MsgEditValidator) Type() string { return EditValidator } type Delegate struct {
// Signer ...
func (msg MsgEditValidator) Signer() common.Address { return msg.StakingAddress }
// MsgDelegate - struct for bonding transactions
type MsgDelegate struct {
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"`
ValidatorAddress common.Address `json:"validator_address" yaml:"validator_address"` ValidatorAddress common.Address `json:"validator_address" yaml:"validator_address"`
Amount *big.Int `json:"amount" yaml:"amount"` Amount *big.Int `json:"amount" yaml:"amount"`
} }
// NewMsgDelegate creates a new MsgDelegate. // Redelegate - type for reassigning delegation
func NewMsgDelegate( type Redelegate struct {
validatorAddress common.Address, delegatorAddress common.Address, amount *big.Int) MsgDelegate {
return MsgDelegate{
DelegatorAddress: delegatorAddress,
ValidatorAddress: validatorAddress,
Amount: amount,
}
}
// Type ...
func (msg MsgDelegate) Type() string { return Delegate }
// Signer ...
func (msg MsgDelegate) Signer() common.Address { return msg.DelegatorAddress }
// MsgRedelegate - struct for re-bonding transactions
type MsgRedelegate struct {
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"`
ValidatorSrcAddress common.Address `json:"validator_src_address" yaml:"validator_src_address"` ValidatorSrcAddress common.Address `json:"validator_src_address" yaml:"validator_src_address"`
ValidatorDstAddress common.Address `json:"validator_dst_address" yaml:"validator_dst_address"` ValidatorDstAddress common.Address `json:"validator_dst_address" yaml:"validator_dst_address"`
Amount *big.Int `json:"amount" yaml:"amount"` Amount *big.Int `json:"amount" yaml:"amount"`
} }
// NewMsgRedelegate creates a new MsgRedelegate. // Undelegate - type for removing delegation responsibility
func NewMsgRedelegate(delAddr, valSrcAddr, valDstAddr common.Address, amount *big.Int) MsgRedelegate { type Undelegate struct {
return MsgRedelegate{
DelegatorAddress: delAddr,
ValidatorSrcAddress: valSrcAddr,
ValidatorDstAddress: valDstAddr,
Amount: amount,
}
}
// Type ...
func (msg MsgRedelegate) Type() string { return Redelegate }
// Signer ...
func (msg MsgRedelegate) Signer() common.Address { return msg.DelegatorAddress }
// MsgUndelegate - struct for unbonding transactions
type MsgUndelegate struct {
DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"` DelegatorAddress common.Address `json:"delegator_address" yaml:"delegator_address"`
ValidatorAddress common.Address `json:"validator_address" yaml:"validator_address"` ValidatorAddress common.Address `json:"validator_address" yaml:"validator_address"`
Amount *big.Int `json:"amount" yaml:"amount"` Amount *big.Int `json:"amount" yaml:"amount"`
} }
// NewMsgUndelegate creates a new MsgUndelegate.
func NewMsgUndelegate(delAddr common.Address, valAddr common.Address, amount *big.Int) MsgUndelegate {
return MsgUndelegate{
DelegatorAddress: delAddr,
ValidatorAddress: valAddr,
Amount: amount,
}
}
// Type ...
func (msg MsgUndelegate) Type() string { return Undelegate }
// Signer ...
func (msg MsgUndelegate) Signer() common.Address { return msg.DelegatorAddress }

@ -1,218 +1,207 @@
package types package types
import ( // var (
"math/big" // minSelfDelegation = big.NewInt(1000)
"reflect" // stakeAmount = big.NewInt(2000)
"testing" // delegateAmount = big.NewInt(500)
// validatorAddress = common.Address(common.MustBech32ToAddress("one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy"))
"github.com/ethereum/go-ethereum/rlp" // validatorAddress2 = common.Address(common.MustBech32ToAddress("one1d2rngmem4x2c6zxsjjz29dlah0jzkr0k2n88wc"))
"github.com/harmony-one/harmony/crypto/bls" // delegatorAddress = common.Address(common.MustBech32ToAddress("one16qsd5ant9v94jrs89mruzx62h7ekcfxmduh2rx"))
"github.com/harmony-one/harmony/internal/common" // blsPubKey = bls.RandPrivateKey().GetPublicKey()
"github.com/harmony-one/harmony/shard" // )
)
// func TestMsgCreateValidatorRLP(t *testing.T) {
var ( // commissionRate := NewDecWithPrec(1, 2) // 10%
minSelfDelegation = big.NewInt(1000) // maxRate := NewDecWithPrec(2, 2) // 20%
stakeAmount = big.NewInt(2000) // maxChangeRate := NewDecWithPrec(1, 3) // 1%
delegateAmount = big.NewInt(500)
validatorAddress = common.MustBech32ToAddress("one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy") // blsPublickey := shard.BlsPublicKey{}
validatorAddress2 = common.MustBech32ToAddress("one1d2rngmem4x2c6zxsjjz29dlah0jzkr0k2n88wc") // blsPublickey.FromLibBLSPublicKey(blsPubKey)
delegatorAddress = common.MustBech32ToAddress("one16qsd5ant9v94jrs89mruzx62h7ekcfxmduh2rx")
blsPubKey = bls.RandPrivateKey().GetPublicKey() // msgCreateValidator := NewMsgCreateValidator(Description{
) // Name: "validator 1",
// Identity: "1",
func TestMsgCreateValidatorRLP(t *testing.T) { // Website: "harmony.one",
commissionRate := NewDecWithPrec(1, 2) // 10% // SecurityContact: "11.111.1111",
maxRate := NewDecWithPrec(2, 2) // 20% // Details: "the best validator ever",
maxChangeRate := NewDecWithPrec(1, 3) // 1% // }, CommissionRates{
// Rate: commissionRate,
blsPublickey := shard.BlsPublicKey{} // MaxRate: maxRate,
blsPublickey.FromLibBLSPublicKey(blsPubKey) // MaxChangeRate: maxChangeRate,
// }, minSelfDelegation, validatorAddress, blsPublickey, stakeAmount)
msgCreateValidator := NewMsgCreateValidator(Description{
Name: "validator 1", // rlpBytes, err := rlp.EncodeToBytes(msgCreateValidator)
Identity: "1", // if err != nil {
Website: "harmony.one", // t.Error("failed to rlp encode 'create validator' message")
SecurityContact: "11.111.1111", // }
Details: "the best validator ever",
}, CommissionRates{ // decodedMsg := &MsgCreateValidator{}
Rate: commissionRate, // err = rlp.DecodeBytes(rlpBytes, decodedMsg)
MaxRate: maxRate,
MaxChangeRate: maxChangeRate, // if err != nil {
}, minSelfDelegation, validatorAddress, blsPublickey, stakeAmount) // t.Error("failed to rlp decode 'create validator' message")
// }
rlpBytes, err := rlp.EncodeToBytes(msgCreateValidator)
if err != nil { // if !decodedMsg.Commission.Rate.Equal(msgCreateValidator.Commission.Rate) {
t.Error("failed to rlp encode 'create validator' message") // t.Error("Commission rate does not match")
} // }
decodedMsg := &MsgCreateValidator{} // if !decodedMsg.Commission.MaxRate.Equal(msgCreateValidator.Commission.MaxRate) {
err = rlp.DecodeBytes(rlpBytes, decodedMsg) // t.Error("MaxRate does not match")
// }
if err != nil {
t.Error("failed to rlp decode 'create validator' message") // if !decodedMsg.Commission.MaxChangeRate.Equal(msgCreateValidator.Commission.MaxChangeRate) {
} // t.Error("MaxChangeRate does not match")
// }
if !decodedMsg.Commission.Rate.Equal(msgCreateValidator.Commission.Rate) {
t.Error("Commission rate does not match") // if !reflect.DeepEqual(decodedMsg.Description, msgCreateValidator.Description) {
} // t.Error("Description does not match")
// }
if !decodedMsg.Commission.MaxRate.Equal(msgCreateValidator.Commission.MaxRate) {
t.Error("MaxRate does not match") // if decodedMsg.MinSelfDelegation.Cmp(msgCreateValidator.MinSelfDelegation) != 0 {
} // t.Error("MinSelfDelegation does not match")
// }
if !decodedMsg.Commission.MaxChangeRate.Equal(msgCreateValidator.Commission.MaxChangeRate) {
t.Error("MaxChangeRate does not match") // if decodedMsg.StakingAddress.String() != msgCreateValidator.StakingAddress.String() {
} // t.Error("StakingAddress does not match")
// }
if !reflect.DeepEqual(decodedMsg.Description, msgCreateValidator.Description) {
t.Error("Description does not match") // if shard.CompareBlsPublicKey(decodedMsg.ValidatingPubKey, msgCreateValidator.ValidatingPubKey) != 0 {
} // t.Error("ValidatingPubKey does not match")
// }
if decodedMsg.MinSelfDelegation.Cmp(msgCreateValidator.MinSelfDelegation) != 0 {
t.Error("MinSelfDelegation does not match") // if decodedMsg.Amount.Cmp(msgCreateValidator.Amount) != 0 {
} // t.Error("Amount does not match")
// }
if decodedMsg.StakingAddress.Hex() != msgCreateValidator.StakingAddress.Hex() { // }
t.Error("StakingAddress does not match")
} // func TestMsgEditValidatorRLP(t *testing.T) {
// commissionRate := NewDecWithPrec(1, 2) // 10%
if shard.CompareBlsPublicKey(decodedMsg.ValidatingPubKey, msgCreateValidator.ValidatingPubKey) != 0 {
t.Error("ValidatingPubKey does not match") // blsPublickey := shard.BlsPublicKey{}
} // blsPublickey.FromLibBLSPublicKey(blsPubKey)
if decodedMsg.Amount.Cmp(msgCreateValidator.Amount) != 0 { // msgEditValidator := NewMsgEditValidator(Description{
t.Error("Amount does not match") // Name: "validator 1",
} // Identity: "1",
} // Website: "harmony.one",
// SecurityContact: "11.111.1111",
func TestMsgEditValidatorRLP(t *testing.T) { // Details: "the best validator ever",
commissionRate := NewDecWithPrec(1, 2) // 10% // }, validatorAddress, commissionRate, minSelfDelegation)
blsPublickey := shard.BlsPublicKey{} // rlpBytes, err := rlp.EncodeToBytes(msgEditValidator)
blsPublickey.FromLibBLSPublicKey(blsPubKey) // if err != nil {
// t.Error("failed to rlp encode 'create validator' message")
msgEditValidator := NewMsgEditValidator(Description{ // }
Name: "validator 1",
Identity: "1", // decodedMsg := &MsgEditValidator{}
Website: "harmony.one", // err = rlp.DecodeBytes(rlpBytes, decodedMsg)
SecurityContact: "11.111.1111",
Details: "the best validator ever", // if err != nil {
}, validatorAddress, commissionRate, minSelfDelegation) // t.Error("failed to rlp decode 'create validator' message")
// }
rlpBytes, err := rlp.EncodeToBytes(msgEditValidator)
if err != nil { // if !reflect.DeepEqual(decodedMsg.Description, msgEditValidator.Description) {
t.Error("failed to rlp encode 'create validator' message") // t.Error("Description does not match")
} // }
decodedMsg := &MsgEditValidator{} // if decodedMsg.StakingAddress.String() != msgEditValidator.StakingAddress.String() {
err = rlp.DecodeBytes(rlpBytes, decodedMsg) // t.Error("StakingAddress does not match")
// }
if err != nil {
t.Error("failed to rlp decode 'create validator' message") // if !decodedMsg.CommissionRate.Equal(msgEditValidator.CommissionRate) {
} // t.Error("Commission rate does not match")
// }
if !reflect.DeepEqual(decodedMsg.Description, msgEditValidator.Description) {
t.Error("Description does not match") // if decodedMsg.MinSelfDelegation.Cmp(msgEditValidator.MinSelfDelegation) != 0 {
} // t.Error("MinSelfDelegation does not match")
// }
if decodedMsg.StakingAddress.Hex() != msgEditValidator.StakingAddress.Hex() { // }
t.Error("StakingAddress does not match")
} // func TestMsgDelegateRLP(t *testing.T) {
// msgDelegate := NewMsgDelegate(delegatorAddress, validatorAddress, delegateAmount)
if !decodedMsg.CommissionRate.Equal(msgEditValidator.CommissionRate) {
t.Error("Commission rate does not match") // rlpBytes, err := rlp.EncodeToBytes(msgDelegate)
} // if err != nil {
// t.Error("failed to rlp encode 'create validator' message")
if decodedMsg.MinSelfDelegation.Cmp(msgEditValidator.MinSelfDelegation) != 0 { // }
t.Error("MinSelfDelegation does not match")
} // decodedMsg := &MsgDelegate{}
} // err = rlp.DecodeBytes(rlpBytes, decodedMsg)
func TestMsgDelegateRLP(t *testing.T) { // if err != nil {
msgDelegate := NewMsgDelegate(delegatorAddress, validatorAddress, delegateAmount) // t.Error("failed to rlp decode 'create validator' message")
// }
rlpBytes, err := rlp.EncodeToBytes(msgDelegate)
if err != nil { // if decodedMsg.DelegatorAddress.String() != msgDelegate.DelegatorAddress.String() {
t.Error("failed to rlp encode 'create validator' message") // t.Error("DelegatorAddress does not match")
} // }
decodedMsg := &MsgDelegate{} // if decodedMsg.ValidatorAddress.String() != msgDelegate.ValidatorAddress.String() {
err = rlp.DecodeBytes(rlpBytes, decodedMsg) // t.Error("ValidatorAddress does not match")
// }
if err != nil {
t.Error("failed to rlp decode 'create validator' message") // if decodedMsg.Amount.Cmp(msgDelegate.Amount) != 0 {
} // t.Error("Amount does not match")
// }
if decodedMsg.DelegatorAddress.Hex() != msgDelegate.DelegatorAddress.Hex() { // }
t.Error("DelegatorAddress does not match")
} // func TestMsgRedelegateRLP(t *testing.T) {
// msgRedelegate := NewMsgRedelegate(delegatorAddress, validatorAddress, validatorAddress2, delegateAmount)
if decodedMsg.ValidatorAddress.Hex() != msgDelegate.ValidatorAddress.Hex() {
t.Error("ValidatorAddress does not match") // rlpBytes, err := rlp.EncodeToBytes(msgRedelegate)
} // if err != nil {
// t.Error("failed to rlp encode 'create validator' message")
if decodedMsg.Amount.Cmp(msgDelegate.Amount) != 0 { // }
t.Error("Amount does not match")
} // decodedMsg := &MsgRedelegate{}
} // err = rlp.DecodeBytes(rlpBytes, decodedMsg)
func TestMsgRedelegateRLP(t *testing.T) { // if err != nil {
msgRedelegate := NewMsgRedelegate(delegatorAddress, validatorAddress, validatorAddress2, delegateAmount) // t.Error("failed to rlp decode 'create validator' message")
// }
rlpBytes, err := rlp.EncodeToBytes(msgRedelegate)
if err != nil { // if decodedMsg.DelegatorAddress.String() != msgRedelegate.DelegatorAddress.String() {
t.Error("failed to rlp encode 'create validator' message") // t.Error("DelegatorAddress does not match")
} // }
decodedMsg := &MsgRedelegate{} // if decodedMsg.ValidatorSrcAddress.String() != msgRedelegate.ValidatorSrcAddress.String() {
err = rlp.DecodeBytes(rlpBytes, decodedMsg) // t.Error("ValidatorSrcAddress does not match")
// }
if err != nil {
t.Error("failed to rlp decode 'create validator' message") // if decodedMsg.ValidatorDstAddress.String() != msgRedelegate.ValidatorDstAddress.String() {
} // t.Error("ValidatorDstAddress does not match")
// }
if decodedMsg.DelegatorAddress.Hex() != msgRedelegate.DelegatorAddress.Hex() {
t.Error("DelegatorAddress does not match") // if decodedMsg.Amount.Cmp(msgRedelegate.Amount) != 0 {
} // t.Error("Amount does not match")
// }
if decodedMsg.ValidatorSrcAddress.Hex() != msgRedelegate.ValidatorSrcAddress.Hex() { // }
t.Error("ValidatorSrcAddress does not match")
} // func TestMsgUndelegateRLP(t *testing.T) {
// msgUndelegate := NewMsgUndelegate(delegatorAddress, validatorAddress, delegateAmount)
if decodedMsg.ValidatorDstAddress.Hex() != msgRedelegate.ValidatorDstAddress.Hex() {
t.Error("ValidatorDstAddress does not match") // rlpBytes, err := rlp.EncodeToBytes(msgUndelegate)
} // if err != nil {
// t.Error("failed to rlp encode 'create validator' message")
if decodedMsg.Amount.Cmp(msgRedelegate.Amount) != 0 { // }
t.Error("Amount does not match")
} // decodedMsg := &MsgUndelegate{}
} // err = rlp.DecodeBytes(rlpBytes, decodedMsg)
func TestMsgUndelegateRLP(t *testing.T) {
msgUndelegate := NewMsgUndelegate(delegatorAddress, validatorAddress, delegateAmount)
rlpBytes, err := rlp.EncodeToBytes(msgUndelegate)
if err != nil {
t.Error("failed to rlp encode 'create validator' message")
}
decodedMsg := &MsgUndelegate{}
err = rlp.DecodeBytes(rlpBytes, decodedMsg)
if err != nil { // if err != nil {
t.Error("failed to rlp decode 'create validator' message") // t.Error("failed to rlp decode 'create validator' message")
} // }
if decodedMsg.DelegatorAddress.Hex() != msgUndelegate.DelegatorAddress.Hex() { // if decodedMsg.DelegatorAddress.String() != msgUndelegate.DelegatorAddress.String() {
t.Error("DelegatorAddress does not match") // t.Error("DelegatorAddress does not match")
} // }
if decodedMsg.ValidatorAddress.Hex() != msgUndelegate.ValidatorAddress.Hex() { // if decodedMsg.ValidatorAddress.String() != msgUndelegate.ValidatorAddress.String() {
t.Error("ValidatorAddress does not match") // t.Error("ValidatorAddress does not match")
} // }
if decodedMsg.Amount.Cmp(msgUndelegate.Amount) != 0 { // if decodedMsg.Amount.Cmp(msgUndelegate.Amount) != 0 {
t.Error("Amount does not match") // t.Error("Amount does not match")
} // }
} // }

@ -0,0 +1,199 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// 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/>.
package types
import (
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/crypto/hash"
)
// sigCache is used to cache the derived sender and contains
// the signer used to derive it.
type sigCache struct {
signer Signer
from common.Address
}
// Sign signs the stake using the given signer and private key
func Sign(tx *StakingTransaction, s Signer, prv *ecdsa.PrivateKey) (*StakingTransaction, error) {
h := s.Hash(tx)
sig, err := crypto.Sign(h[:], prv)
if err != nil {
return nil, err
}
return tx.WithSignature(s, sig)
}
// Sender returns the address derived from the signature (V, R, S) using secp256k1
// elliptic curve and an error if it failed deriving or upon an incorrect
// signature.
//
// Sender may cache the address, allowing it to be used regardless of
// signing method. The cache is invalidated if the cached signer does
// not match the signer used in the current call.
func Sender(signer Signer, tx *StakingTransaction) (common.Address, error) {
if sc := tx.from.Load(); sc != nil {
sigCache := sc.(sigCache)
// If the signer used to derive from in a previous
// call is not the same as used current, invalidate
// the cache.
if sigCache.signer.Equal(signer) {
return sigCache.from, nil
}
}
addr, err := signer.Sender(tx)
if err != nil {
return common.Address{}, err
}
tx.from.Store(sigCache{signer: signer, from: addr})
return addr, nil
}
// Signer encapsulates transaction signature handling. Note that this interface is not a
// stable API and may change at any time to accommodate new protocol rules.
type Signer interface {
// Sender returns the sender address of the transaction.
Sender(tx *StakingTransaction) (common.Address, error)
// SignatureValues returns the raw R, S, V values corresponding to the
// given signature.
SignatureValues(tx *StakingTransaction, sig []byte) (r, s, v *big.Int, err error)
// Hash returns the hash to be signed.
Hash(tx *StakingTransaction) common.Hash
// Equal returns true if the given signer is the same as the receiver.
Equal(s Signer) bool
}
// EIP155Signer implements Signer using the EIP155 rules.
type EIP155Signer struct {
chainID, chainIDMul *big.Int
}
// NewEIP155Signer creates a EIP155Signer given chainID.
func NewEIP155Signer(chainID *big.Int) EIP155Signer {
if chainID == nil {
chainID = new(big.Int)
}
return EIP155Signer{
chainID: chainID,
chainIDMul: new(big.Int).Mul(chainID, big.NewInt(2)),
}
}
// Equal checks if the given EIP155Signer is equal to another Signer.
func (s EIP155Signer) Equal(s2 Signer) bool {
eip155, ok := s2.(EIP155Signer)
return ok && eip155.chainID.Cmp(s.chainID) == 0
}
var big8 = big.NewInt(8)
// Sender returns the sender address of the given signer.
func (s EIP155Signer) Sender(tx *StakingTransaction) (common.Address, error) {
if tx.ChainID().Cmp(s.chainID) != 0 {
return common.Address{}, core.ErrInvalidChainID
}
V := new(big.Int).Sub(tx.data.V, s.chainIDMul)
V.Sub(V, big8)
return recoverPlain(s.Hash(tx), tx.data.R, tx.data.S, V, true)
}
// SignatureValues returns signature values. This signature
// needs to be in the [R || S || V] format where V is 0 or 1.
func (s EIP155Signer) SignatureValues(
tx *StakingTransaction, sig []byte,
) (R, S, V *big.Int, err error) {
sigValues := func(tx *StakingTransaction, sig []byte) (r, s, v *big.Int, err error) {
if len(sig) != 65 {
panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig)))
}
r = new(big.Int).SetBytes(sig[:32])
s = new(big.Int).SetBytes(sig[32:64])
v = new(big.Int).SetBytes([]byte{sig[64] + 27})
return r, s, v, nil
}
R, S, V, err = sigValues(tx, sig)
if err != nil {
return nil, nil, nil, err
}
if s.chainID.Sign() != 0 {
V = big.NewInt(int64(sig[64] + 35))
V.Add(V, s.chainIDMul)
}
return R, S, V, nil
}
// Hash returns the hash to be signed by the sender.
// It does not uniquely identify the transaction.
func (s EIP155Signer) Hash(tx *StakingTransaction) common.Hash {
return hash.FromRLP([]interface{}{
tx.data.Directive,
tx.data.StakeMsg,
tx.data.AccountNonce,
tx.data.Price,
tx.data.GasLimit,
s.chainID, uint(0), uint(0),
})
}
func recoverPlain(
sighash common.Hash, R, S, Vb *big.Int, homestead bool,
) (common.Address, error) {
if Vb.BitLen() > 8 {
return common.Address{}, ErrInvalidSig
}
V := byte(Vb.Uint64() - 27)
if !crypto.ValidateSignatureValues(V, R, S, homestead) {
return common.Address{}, ErrInvalidSig
}
// encode the signature in uncompressed format
r, s := R.Bytes(), S.Bytes()
sig := make([]byte, 65)
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)
sig[64] = V
// recover the public key from the signature
pub, err := crypto.Ecrecover(sighash[:], sig)
if err != nil {
return common.Address{}, err
}
if len(pub) == 0 || pub[0] != 4 {
return common.Address{}, errors.New("invalid public key")
}
var addr common.Address
copy(addr[:], crypto.Keccak256(pub[1:])[12:])
return addr, nil
}
// deriveChainID derives the chain id from the given v parameter
func deriveChainID(v *big.Int) *big.Int {
if v.BitLen() <= 64 {
v := v.Uint64()
if v == 27 || v == 28 {
return new(big.Int)
}
return new(big.Int).SetUint64((v - 35) / 2)
}
v = new(big.Int).Sub(v, big.NewInt(35))
return v.Div(v, big.NewInt(2))
}

@ -1,39 +0,0 @@
package types
import (
"bytes"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/crypto/hash"
)
// StakingTransaction struct.
type StakingTransaction struct {
AccountNonce uint64 `json:"nonce" gencodec:"required"`
Price *big.Int `json:"gasPrice" gencodec:"required"`
GasLimit uint64 `json:"gas" gencodec:"required"`
Msg StakingMessage `json:"msg" gencodec:"required"`
// Signature values
V *big.Int `json:"v" gencodec:"required"`
R *big.Int `json:"r" gencodec:"required"`
S *big.Int `json:"s" gencodec:"required"`
// This is only used when marshaling to JSON.
hash *common.Hash `json:"hash" rlp:"-"`
}
// StakingTransactions is a Transaction slice type for basic sorting.
type StakingTransactions []*StakingTransaction
// Hash hashes the RLP encoding of tx.
// It uniquely identifies the transaction.
func (tx *StakingTransaction) Hash() common.Hash {
emptyHash := common.Hash{}
if bytes.Compare(tx.hash[:], emptyHash[:]) == 0 {
h := hash.FromRLP(tx)
tx.hash = &h
}
return *tx.hash
}

@ -0,0 +1,110 @@
package types
import (
"errors"
"io"
"math/big"
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/crypto/hash"
)
type txdata struct {
Directive
StakeMsg interface{}
AccountNonce uint64 `json:"nonce" gencodec:"required"`
Price *big.Int `json:"gasPrice" gencodec:"required"`
GasLimit uint64 `json:"gas" gencodec:"required"`
// Signature values
V *big.Int `json:"v" gencodec:"required"`
R *big.Int `json:"r" gencodec:"required"`
S *big.Int `json:"s" gencodec:"required"`
// This is only used when marshaling to JSON.
Hash *common.Hash `json:"hash" rlp:"-"`
}
// StakingTransaction is a record captuing all staking operations
type StakingTransaction struct {
data txdata
// caches
hash atomic.Value
size atomic.Value
from atomic.Value
}
type fulfill func() (Directive, interface{})
// NewStakingTransaction produces a new staking transaction record
func NewStakingTransaction(
nonce, gasLimit uint64, gasPrice *big.Int, f fulfill,
) (*StakingTransaction, error) {
directive, payload := f()
// TODO(Double check that this is legitmate directive)
newStake := &StakingTransaction{data: txdata{
directive,
payload,
nonce,
big.NewInt(0).Set(gasPrice),
gasLimit,
big.NewInt(0),
big.NewInt(0),
big.NewInt(0),
nil,
}}
return newStake, nil
}
var (
// ErrInvalidSig is a bad signature
ErrInvalidSig = errors.New("invalid transaction v, r, s values")
)
// StakingTransactions is a stake slice type for basic sorting.
type StakingTransactions []*StakingTransaction
// Hash hashes the RLP encoding of tx.
// It uniquely identifies the transaction.
func (tx *StakingTransaction) Hash() common.Hash {
if hash := tx.hash.Load(); hash != nil {
return hash.(common.Hash)
}
v := hash.FromRLP(tx)
tx.hash.Store(v)
return v
}
// WithSignature returns a new transaction with the given signature.
func (tx *StakingTransaction) WithSignature(signer Signer, sig []byte) (*StakingTransaction, error) {
r, s, v, err := signer.SignatureValues(tx, sig)
if err != nil {
return nil, err
}
cpy := &StakingTransaction{data: tx.data}
cpy.data.R, cpy.data.S, cpy.data.V = r, s, v
return cpy, nil
}
// ChainID is what chain this staking transaction for
func (tx *StakingTransaction) ChainID() *big.Int {
return deriveChainID(tx.data.V)
}
// EncodeRLP implements rlp.Encoder
func (tx *StakingTransaction) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, &tx.data)
}
// DecodeRLP implements rlp.Decoder
func (tx *StakingTransaction) DecodeRLP(s *rlp.Stream) error {
_, size, _ := s.Kind()
err := s.Decode(&tx.data)
if err != nil {
return err
}
if err == nil {
tx.size.Store(common.StorageSize(rlp.ListSize(size)))
}
return err
}

@ -7,19 +7,28 @@ import (
"github.com/harmony-one/harmony/internal/common" "github.com/harmony-one/harmony/internal/common"
) )
// Define validator staking related const
const (
MaxNameLength = 70
MaxIdentityLength = 3000
MaxWebsiteLength = 140
MaxSecurityContactLength = 140
MaxDetailsLength = 280
)
// 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 Address common.Address `json:"address" yaml:"address"` // 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 ValidatingPubKey bls.PublicKey `json:"validating_pub_key" yaml:"validating_pub_key"` // The BLS public key of the validator for consensus
Description Description `json:"description" yaml:"description"` // description for the validator Description Description `json:"description" yaml:"description"` // description for the validator
Active bool `json:"active" yaml:"active"` // Is the validator active in the validating process or not Active bool `json:"active" yaml:"active"` // Is the validator active in the validating process or not
Stake big.Int `json:"stake" yaml:"stake"` // The stake put by the validator itself Stake *big.Int `json:"stake" yaml:"stake"` // 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 UnbondingHeight *big.Int `json:"unbonding_height" yaml:"unbonding_height"` // if unbonding, height at which this validator has begun unbonding
Commission Commission `json:"commission" yaml:"commission"` // commission parameters Commission Commission `json:"commission" yaml:"commission"` // commission parameters
MinSelfDelegation big.Int `json:"min_self_delegation" yaml:"min_self_delegation"` // validator's self declared minimum self delegation MinSelfDelegation *big.Int `json:"min_self_delegation" yaml:"min_self_delegation"` // validator's self declared minimum self delegation
} }
// Description - description fields for a validator // Description - some possible IRL connections
type Description struct { type Description struct {
Name string `json:"name" yaml:"name"` // name Name string `json:"name" yaml:"name"` // name
Identity string `json:"identity" yaml:"identity"` // optional identity signature (ex. UPort or Keybase) Identity string `json:"identity" yaml:"identity"` // optional identity signature (ex. UPort or Keybase)

@ -6,21 +6,18 @@ import (
"log" "log"
"math/big" "math/big"
types2 "github.com/harmony-one/harmony/staking/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
blockfactory "github.com/harmony-one/harmony/block/factory" "github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/harmony/crypto/hash"
"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/core" "github.com/harmony-one/harmony/core"
core_state "github.com/harmony-one/harmony/core/state" 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/hash"
"github.com/harmony-one/harmony/internal/params" "github.com/harmony-one/harmony/internal/params"
pkgworker "github.com/harmony-one/harmony/node/worker" pkgworker "github.com/harmony-one/harmony/node/worker"
staking "github.com/harmony-one/harmony/staking/types"
) )
const ( const (
@ -129,7 +126,7 @@ func fundFaucetContract(chain *core.BlockChain) {
amount := 720000 amount := 720000
tx, _ := types.SignTx(types.NewTransaction(nonce+uint64(4), StakingAddress, 0, big.NewInt(int64(amount)), params.TxGas, nil, nil), types.HomesteadSigner{}, FaucetPriKey) tx, _ := types.SignTx(types.NewTransaction(nonce+uint64(4), StakingAddress, 0, big.NewInt(int64(amount)), params.TxGas, nil, nil), types.HomesteadSigner{}, FaucetPriKey)
txs = append(txs, tx) txs = append(txs, tx)
err := contractworker.CommitTransactions(txs, types2.StakingTransactions{}, testUserAddress) err := contractworker.CommitTransactions(txs, staking.StakingTransactions{}, testUserAddress)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
@ -167,7 +164,7 @@ func callFaucetContractToFundAnAddress(chain *core.BlockChain) {
callEnc = append(callEnc, paddedAddress...) callEnc = append(callEnc, paddedAddress...)
callfaucettx, _ := types.SignTx(types.NewTransaction(nonce+uint64(5), faucetContractAddress, 0, big.NewInt(0), params.TxGasContractCreation*10, nil, callEnc), types.HomesteadSigner{}, FaucetPriKey) callfaucettx, _ := types.SignTx(types.NewTransaction(nonce+uint64(5), faucetContractAddress, 0, big.NewInt(0), params.TxGasContractCreation*10, nil, callEnc), types.HomesteadSigner{}, FaucetPriKey)
err = contractworker.CommitTransactions(types.Transactions{callfaucettx}, types2.StakingTransactions{}, testUserAddress) err = contractworker.CommitTransactions(types.Transactions{callfaucettx}, staking.StakingTransactions{}, testUserAddress)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
@ -245,7 +242,7 @@ func playStaking(chain *core.BlockChain) {
tx, _ := types.SignTx(types.NewTransaction(0, stakeContractAddress, 0, big.NewInt(int64(stake)), params.TxGas*5, nil, callEncl), types.HomesteadSigner{}, allRandomUserKey[i]) tx, _ := types.SignTx(types.NewTransaction(0, stakeContractAddress, 0, big.NewInt(int64(stake)), params.TxGas*5, nil, callEncl), types.HomesteadSigner{}, allRandomUserKey[i])
stakingtxns = append(stakingtxns, tx) stakingtxns = append(stakingtxns, tx)
} }
err = contractworker.CommitTransactions(stakingtxns, types2.StakingTransactions{}, common.Address{}) err = contractworker.CommitTransactions(stakingtxns, staking.StakingTransactions{}, common.Address{})
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
@ -303,7 +300,7 @@ func playWithdrawStaking(chain *core.BlockChain) {
withdrawstakingtxns = append(withdrawstakingtxns, tx) withdrawstakingtxns = append(withdrawstakingtxns, tx)
} }
err = contractworker.CommitTransactions(withdrawstakingtxns, types2.StakingTransactions{}, common.Address{}) err = contractworker.CommitTransactions(withdrawstakingtxns, staking.StakingTransactions{}, common.Address{})
if err != nil { if err != nil {
fmt.Println("error:") fmt.Println("error:")
fmt.Println(err) fmt.Println(err)

Loading…
Cancel
Save