Merge pull request #512 from harmony-one/rj_branch

Add faucet call before staking tx
pull/517/head
Rongjian Lan 6 years ago committed by GitHub
commit e87828904a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      api/service/discovery/service.go
  2. 23
      api/service/staking/service.go
  3. 6
      cmd/harmony.go
  4. 2
      consensus/consensus.go
  5. 2
      consensus/consensus_leader.go
  6. 3
      consensus/consensus_validator.go
  7. 2
      contracts/Faucet.sol
  8. 15
      internal/utils/contract/constants.go
  9. 22
      internal/utils/utils.go
  10. 41
      node/contract.go
  11. 36
      node/node.go
  12. 18
      node/node_genesis.go
  13. 16
      node/node_handler.go
  14. 2
      node/node_newblock.go
  15. 5
      node/service_setup.go
  16. 56
      node/staking.go
  17. 3
      test/deploy.sh
  18. 1
      test/deploy_newnode.sh

@ -139,7 +139,7 @@ func (s *Service) contactP2pPeers() {
if err != nil {
utils.GetLogInstance().Error("[DISCOVERY] Failed to send ping message", "group", g)
} else {
utils.GetLogInstance().Info("[DISCOVERY]", "Sent Ping Message", g)
//utils.GetLogInstance().Info("[DISCOVERY]", "Sent Ping Message", g)
}
}
}

@ -2,7 +2,6 @@ package staking
import (
"crypto/ecdsa"
"fmt"
"math/big"
"time"
@ -30,6 +29,8 @@ const (
WaitTime = 5 * time.Second
// StakingContractAddress is the staking deployed contract address
StakingContractAddress = "TODO(minhdoan): Create a PR to generate staking contract address"
// StakingAmount is the amount of stake to put
StakingAmount = 10
)
// State is the state of staking service.
@ -50,13 +51,13 @@ type Service struct {
}
// New returns staking service.
func New(host p2p.Host, accountKey *ecdsa.PrivateKey, stakingAmount int64, beaconChain *core.BlockChain) *Service {
func New(host p2p.Host, accountKey *ecdsa.PrivateKey, beaconChain *core.BlockChain) *Service {
return &Service{
host: host,
stopChan: make(chan struct{}),
stoppedChan: make(chan struct{}),
accountKey: accountKey,
stakingAmount: stakingAmount,
stakingAmount: StakingAmount,
beaconChain: beaconChain,
}
}
@ -82,6 +83,7 @@ func (s *Service) Run() {
return
}
s.DoService()
return
case <-s.stopChan:
return
}
@ -135,9 +137,14 @@ func (s *Service) getStakingInfo() *proto.StakingContractInfoResponse {
func (s *Service) getFakeStakingInfo() *proto.StakingContractInfoResponse {
balance := big.NewInt(params.Ether)
nonce := uint64(0)
nonce := uint64(0) // TODO: make it a incrementing field
priKey := contract_constants.GenesisBeaconAccountPriKey
contractAddress := crypto.PubkeyToAddress(priKey.PublicKey)
stakingContractAddress := crypto.CreateAddress(contractAddress, uint64(nonce))
return &proto.StakingContractInfoResponse{
ContractAddress: fmt.Sprintf("%s", contract_constants.DeployedContractAddress),
ContractAddress: stakingContractAddress.Hex(),
Balance: balance.Bytes(),
Nonce: nonce,
}
@ -173,9 +180,9 @@ func (s *Service) createRawStakingMessage() []byte {
toAddress,
0, // beacon chain.
big.NewInt(s.stakingAmount),
params.CallValueTransferGas*2, // hard-code
big.NewInt(int64(params.Sha256BaseGas)), // pick some predefined gas price.
nil)
params.TxGas*10, // hard-code
nil, // pick some predefined gas price.
common.FromHex("0xd0e30db0")) // Refer to Node.DepositFuncSignature
if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, s.accountKey); err == nil {
ts := types.Transactions{signedTx}

@ -143,7 +143,7 @@ func main() {
var clientPeer *p2p.Peer
var role string
stakingPriKey := utils.LoadStakingKeyFromFile(*stakingKeyFile)
stakingPriKey := node.LoadStakingKeyFromFile(*stakingKeyFile)
nodePriKey, _, err := utils.LoadKeyFromFile(*keyFile)
if err != nil {
@ -180,8 +180,6 @@ func main() {
panic("unable to new host in harmony")
}
log.Info("New Harmony Node...", "multiaddress", fmt.Sprintf("/ip4/%s/tcp/%s/p2p/%s", *ip, *port, host.GetID().Pretty()))
host.AddPeer(&leader)
// Consensus object.
@ -245,6 +243,7 @@ func main() {
}
// Assign closure functions to the consensus object
consensus.BlockVerifier = currentNode.VerifyNewBlock
consensus.OnConsensusDone = currentNode.PostConsensusProcessing
currentNode.State = node.NodeWaitToJoin
@ -252,6 +251,7 @@ func main() {
go currentNode.SendPongMessage()
}
log.Info("New Harmony Node ====", "Role", currentNode.Role, "multiaddress", fmt.Sprintf("/ip4/%s/tcp/%s/p2p/%s", *ip, *port, host.GetID().Pretty()))
go currentNode.SupportSyncing()
currentNode.ServiceManagerSetup()
currentNode.RunServices()

@ -91,6 +91,8 @@ type Consensus struct {
// The post-consensus processing func passed from Node object
// Called when consensus on a new block is done
OnConsensusDone func(*types.Block)
// The verifier func passed from Node object
BlockVerifier func(*types.Block) bool
// current consensus block to check if out of sync
ConsensusBlock chan *BFTBlockInfo

@ -321,7 +321,7 @@ func (consensus *Consensus) processCommitMessage(message *msg_pb.Message) {
consensus.consensusID++
consensus.OnConsensusDone(&blockObj)
utils.GetLogInstance().Debug("HOORAY!!! CONSENSUS REACHED!!!", "consensusID", consensus.consensusID, "numOfSignatures", len(commitSigs))
utils.GetLogInstance().Debug("HOORAY!!!!!!! CONSENSUS REACHED!!!!!!!", "consensusID", consensus.consensusID, "numOfSignatures", len(commitSigs))
// TODO: remove this temporary delay
time.Sleep(500 * time.Millisecond)

@ -262,8 +262,7 @@ func (consensus *Consensus) processCommittedMessage(message *msg_pb.Message) {
utils.GetLogInstance().Debug("failed to construct the new block after consensus")
}
// check block data (transactions
// TODO: change to verify the block body
if err := consensus.VerifyHeader(consensus.ChainReader, blockObj.Header(), true); err != nil {
if err := consensus.VerifyHeader(consensus.ChainReader, blockObj.Header(), false); err != nil {
utils.GetLogInstance().Debug("[WARNING] Block content is not verified successfully", "consensusID", consensus.consensusID)
return
}

@ -1,7 +1,7 @@
pragma solidity >=0.4.22 <0.6.0;
contract Faucet {
mapping(address => bool) processed;
uint quota = 0.5 ether;
uint quota = 10 ether;
address owner;
constructor() public payable {
owner = msg.sender;

@ -2,10 +2,11 @@ package contract
import (
"crypto/ecdsa"
"fmt"
"os"
"strings"
"github.com/harmony-one/harmony/internal/utils"
"github.com/ethereum/go-ethereum/crypto"
)
@ -22,7 +23,7 @@ type DeployAccount struct {
func BeaconAccountPriKey() *ecdsa.PrivateKey {
prikey, err := ecdsa.GenerateKey(crypto.S256(), strings.NewReader(beaconGenesisString))
if err != nil && prikey == nil {
fmt.Println("MINHDOAN***", err)
utils.GetLogInstance().Error("Failed to generate beacon chain contract deployer account")
os.Exit(1)
}
return prikey
@ -37,6 +38,16 @@ var GenesisBeaconAccountPublicKey = GenesisBeaconAccountPriKey.PublicKey
// DeployedContractAddress is the deployed contract address of the staking smart contract in beacon chain.
var DeployedContractAddress = crypto.CreateAddress(crypto.PubkeyToAddress(GenesisBeaconAccountPublicKey), uint64(0))
// StakingAccounts is the accounts only used for staking.
var StakingAccounts = [...]DeployAccount{
{Address: "0xE2bD4413172C98d5094B94de1A8AC6a383d68b84", Private: "e401343197a852f361e38ce6b46c99f1d6d1f80499864c6ae7effee42b46ab6b", Public: "0xE2bD4413172C98d5094B94de1A8AC6a383d68b84"},
{Address: "0x183418934Fd8A97c98E086151317B2df6259b8A8", Private: "a7d764439a7619f703c97ee2a2cf0be2cd62ad4c9deebd5423d6f28de417b907", Public: "0x183418934Fd8A97c98E086151317B2df6259b8A8"},
{Address: "0x9df0e70D4cb3E9beC0548D8Ac56F46596D1BcdB6", Private: "4e3f7c819a15249d2824834cd7ce20fe24d6eab8eb39ac63b78cb3713362cf78", Public: "0x9df0e70D4cb3E9beC0548D8Ac56F46596D1BcdB6"},
{Address: "0x64570B8D2f9028b850340b6710bB0027baC5EFa2", Private: "8565eded3f70b2f8608495fa7e301fefc36cbc03286c0f4e75ffde7e02b49791", Public: "0x64570B8D2f9028b850340b6710bB0027baC5EFa2"},
{Address: "0x7E653426a7E0c1D210A652bf0E74B15838059b80", Private: "23176da901759e231d7b2d8761f3448220fcfd0232ed0b9644689a6ad7d50990", Public: "0x7E653426a7E0c1D210A652bf0E74B15838059b80"},
{Address: "0xAe44500A96756112C69F88008388037F6C6dd723", Private: "a9b4c273ffa398a1b1c8eeab63c40cef2c2fb2fc1fc4de9ab73a61f12e4d990a", Public: "0xAe44500A96756112C69F88008388037F6C6dd723"},
}
// FakeAccounts is the accounts only used for development purpose.
var FakeAccounts = [...]DeployAccount{
{Address: "0xE2bD4413172C98d5094B94de1A8AC6a383d68b84", Private: "e401343197a852f361e38ce6b46c99f1d6d1f80499864c6ae7effee42b46ab6b", Public: "0xE2bD4413172C98d5094B94de1A8AC6a383d68b84"},

@ -2,7 +2,6 @@ package utils
import (
"bytes"
"crypto/ecdsa"
"encoding/binary"
"encoding/json"
"fmt"
@ -14,7 +13,6 @@ import (
"strconv"
"sync"
crypto "github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/p2p"
p2p_crypto "github.com/libp2p/go-libp2p-crypto"
@ -216,23 +214,3 @@ func LoadKeyFromFile(keyfile string) (key p2p_crypto.PrivKey, pk p2p_crypto.PubK
key, pk, err = LoadPrivateKey(keyStruct.Key)
return key, pk, err
}
// LoadStakingKeyFromFile load staking private key from keyfile
// If the private key is not loadable or no file, it will generate
// a new random private key
func LoadStakingKeyFromFile(keyfile string) *ecdsa.PrivateKey {
key, err := crypto.LoadECDSA(keyfile)
if err != nil {
GetLogInstance().Error("no key file. Let's create a staking private key")
key, err = crypto.GenerateKey()
if err != nil {
GetLogInstance().Error("Unable to generate the private key")
os.Exit(1)
}
if err = crypto.SaveECDSA(keyfile, key); err != nil {
GetLogInstance().Error("Unable to save the private key", "error", err)
os.Exit(1)
}
}
return key
}

@ -6,6 +6,8 @@ import (
"math/big"
"strings"
"github.com/harmony-one/harmony/internal/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
@ -37,7 +39,7 @@ func (node *Node) AddStakingContractToPendingTransactions() {
// Unsigned transaction to avoid the case of transaction address.
mycontracttx, _ := types.SignTx(types.NewContractCreation(uint64(0), node.Consensus.ShardID, contractFunds, params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, priKey)
//node.StakingContractAddress = crypto.CreateAddress(contractAddress, uint64(0))
node.StakingContractAddress = node.generateDeployedStakingContractAddress(mycontracttx, contractAddress)
node.StakingContractAddress = node.generateDeployedStakingContractAddress(contractAddress)
node.addPendingTransactions(types.Transactions{mycontracttx})
}
@ -45,9 +47,7 @@ func (node *Node) AddStakingContractToPendingTransactions() {
// (Refer: https://solidity.readthedocs.io/en/v0.5.3/introduction-to-smart-contracts.html#index-8)
// Then we can (re)create the deployed address. Trivially, this is 0 for us.
// The deployed contract address can also be obtained via the receipt of the contract creating transaction.
func (node *Node) generateDeployedStakingContractAddress(mycontracttx *types.Transaction, contractAddress common.Address) common.Address {
//Ideally we send the transaction to
func (node *Node) generateDeployedStakingContractAddress(contractAddress common.Address) common.Address {
//Correct Way 1:
//node.SendTx(mycontracttx)
//receipts := node.worker.GetCurrentReceipts()
@ -56,7 +56,6 @@ func (node *Node) generateDeployedStakingContractAddress(mycontracttx *types.Tra
//Correct Way 2:
//nonce := GetNonce(contractAddress)
//deployedAddress := crypto.CreateAddress(contractAddress, uint64(nonce))
//deployedcontractaddress = recepits[len(receipts)-1].ContractAddress //get the address from the receipt
nonce := 0
return crypto.CreateAddress(contractAddress, uint64(nonce))
}
@ -97,7 +96,7 @@ func (node *Node) getDeployedStakingContract() common.Address {
// AddFaucetContractToPendingTransactions adds the faucet contract the genesis block.
func (node *Node) AddFaucetContractToPendingTransactions() {
// Add a contract deployment transactionv
priKey := node.ContractKeys[0]
priKey := node.ContractDeployerKey
dataEnc := common.FromHex(FaucetContractBinary)
// Unsigned transaction to avoid the case of transaction address.
@ -112,28 +111,38 @@ func (node *Node) AddFaucetContractToPendingTransactions() {
}
// CallFaucetContract invokes the faucet contract to give the walletAddress initial money
func (node *Node) CallFaucetContract(walletAddress common.Address) common.Hash {
return node.createSendingMoneyTransaction(walletAddress)
func (node *Node) CallFaucetContract(address common.Address) common.Hash {
return node.callGetFreeToken(address)
}
func (node *Node) createSendingMoneyTransaction(walletAddress common.Address) common.Hash {
func (node *Node) callGetFreeToken(address common.Address) common.Hash {
state, err := node.blockchain.State()
if err != nil {
log.Error("Failed to get chain state", "Error", err)
}
nonce := state.GetNonce(crypto.PubkeyToAddress(node.ContractKeys[0].PublicKey))
contractData := FaucetFreeMoneyMethodCall + hex.EncodeToString(walletAddress.Bytes())
nonce := state.GetNonce(crypto.PubkeyToAddress(node.ContractDeployerKey.PublicKey))
return node.callGetFreeTokenWithNonce(address, nonce)
}
func (node *Node) callGetFreeTokenWithNonce(address common.Address, nonce uint64) common.Hash {
contractData := FaucetFreeMoneyMethodCall + hex.EncodeToString(address.Bytes())
dataEnc := common.FromHex(contractData)
tx, _ := types.SignTx(types.NewTransaction(nonce, node.ContractAddresses[0], node.Consensus.ShardID, big.NewInt(0), params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, node.ContractKeys[0])
utils.GetLogInstance().Info("Sending Free Token to ", "Address", address.Hex())
tx, _ := types.SignTx(types.NewTransaction(nonce, node.ContractAddresses[0], node.Consensus.ShardID, big.NewInt(0), params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, node.ContractDeployerKey)
node.addPendingTransactions(types.Transactions{tx})
return tx.Hash()
}
// DepositToFakeAccounts invokes the faucet contract to give the walletAddress initial money
func (node *Node) DepositToFakeAccounts() {
for _, deployAccount := range contract.FakeAccounts {
// DepositToStakingAccounts invokes the faucet contract to give the staking accounts initial money
func (node *Node) DepositToStakingAccounts() {
state, err := node.blockchain.State()
if err != nil {
log.Error("Failed to get chain state", "Error", err)
}
nonce := state.GetNonce(crypto.PubkeyToAddress(node.ContractDeployerKey.PublicKey)) + 1 // + 1 because deployer key is already used for faucet contract deployment
for i, deployAccount := range contract.StakingAccounts {
address := common.HexToAddress(deployAccount.Address)
node.createSendingMoneyTransaction(address)
node.callGetFreeTokenWithNonce(address, nonce+uint64(i))
}
}

@ -58,6 +58,26 @@ const (
ClientNode
)
func (role Role) String() string {
switch role {
case Unknown:
return "Unknown"
case ShardLeader:
return "ShardLeader"
case ShardValidator:
return "ShardValidator"
case BeaconLeader:
return "BeaconLeader"
case BeaconValidator:
return "BeaconValidator"
case NewNode:
return "NewNode"
case ClientNode:
return "ClientNode"
}
return "Unknown"
}
func (state State) String() string {
switch state {
case NodeInit:
@ -161,7 +181,7 @@ type Node struct {
// For test only
TestBankKeys []*ecdsa.PrivateKey
ContractKeys []*ecdsa.PrivateKey
ContractDeployerKey *ecdsa.PrivateKey
ContractAddresses []common.Address
// Group Message Receiver
@ -205,11 +225,9 @@ func (node *Node) addPendingTransactions(newTxs types.Transactions) {
func (node *Node) getTransactionsForNewBlock(maxNumTxs int) types.Transactions {
node.pendingTxMutex.Lock()
selected, unselected, invalid := node.Worker.SelectTransactionsForNewBlock(node.pendingTransactions, maxNumTxs)
_ = invalid // invalid txs are discard
utils.GetLogInstance().Debug("Invalid transactions discarded", "number", len(invalid))
node.pendingTransactions = unselected
utils.GetLogInstance().Debug("Remaining pending transactions", "number", len(node.pendingTransactions), "selected", len(selected))
utils.GetLogInstance().Debug("Selecting Transactions", "remainPending", len(node.pendingTransactions), "selected", len(selected), "invalidDiscarded", len(invalid))
node.pendingTxMutex.Unlock()
return selected
}
@ -260,12 +278,16 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, db ethdb.Database) *N
node.TxPool = core.NewTxPool(core.DefaultTxPoolConfig, params.TestChainConfig, chain)
node.Worker = worker.New(params.TestChainConfig, chain, node.Consensus, pki.GetAddressFromPublicKey(node.SelfPeer.PubKey), node.Consensus.ShardID)
if node.Role == BeaconLeader || node.Role == BeaconValidator {
node.CurrentStakes = make(map[common.Address]int64)
}
utils.GetLogInstance().Debug("Created Genesis Block", "blockHash", chain.GetBlockByNumber(0).Hash().Hex())
node.Consensus.ConsensusBlock = make(chan *consensus.BFTBlockInfo)
node.Consensus.VerifiedNewBlock = make(chan *types.Block)
// Setup one time smart contracts
node.AddFaucetContractToPendingTransactions()
node.CurrentStakes = make(map[common.Address]int64)
node.AddStakingContractToPendingTransactions() //This will save the latest information about staked nodes in current staked
node.DepositToStakingAccounts()
}
if consensusObj != nil && consensusObj.IsLeader {

@ -24,18 +24,12 @@ const (
func (node *Node) GenesisBlockSetup(db ethdb.Database) (*core.BlockChain, error) {
// Initialize genesis block and blockchain
genesisAlloc := node.CreateGenesisAllocWithTestingAddresses(FakeAddressNumber)
contractKey, _ := ecdsa.GenerateKey(crypto.S256(), strings.NewReader("Test contract key string stream that is fixed so that generated test key are deterministic every time"))
contractAddress := crypto.PubkeyToAddress(contractKey.PublicKey)
contractFunds := big.NewInt(TotalInitFund)
contractFunds = contractFunds.Mul(contractFunds, big.NewInt(params.Ether))
genesisAlloc[contractAddress] = core.GenesisAccount{Balance: contractFunds}
node.ContractKeys = append(node.ContractKeys, contractKey)
node.AddFaucetContractToPendingTransactions()
if node.Role == BeaconLeader {
node.AddStakingContractToPendingTransactions() //This will save the latest information about staked nodes in current staked
node.DepositToFakeAccounts()
}
contractDeployerKey, _ := ecdsa.GenerateKey(crypto.S256(), strings.NewReader("Test contract key string stream that is fixed so that generated test key are deterministic every time"))
contractDeployerAddress := crypto.PubkeyToAddress(contractDeployerKey.PublicKey)
contractDeployerFunds := big.NewInt(TotalInitFund)
contractDeployerFunds = contractDeployerFunds.Mul(contractDeployerFunds, big.NewInt(params.Ether))
genesisAlloc[contractDeployerAddress] = core.GenesisAccount{Balance: contractDeployerFunds}
node.ContractDeployerKey = contractDeployerKey
chainConfig := params.TestChainConfig
chainConfig.ChainID = big.NewInt(int64(node.Consensus.ShardID)) // Use ChainID as piggybacked ShardID

@ -134,7 +134,7 @@ func (node *Node) messageHandler(content []byte, sender string) {
if node.Role != BeaconLeader {
return
}
node.addStakingTxnIntoPendingTxns(msgPayload)
node.processStakingMessage(msgPayload)
case proto.Node:
actionType := proto_node.MessageType(msgType)
switch actionType {
@ -201,14 +201,14 @@ func (node *Node) messageHandler(content []byte, sender string) {
}
}
func (node *Node) addStakingTxnIntoPendingTxns(msgPayload []byte) {
func (node *Node) processStakingMessage(msgPayload []byte) {
msg := &message.Message{}
err := pb.Unmarshal(msgPayload, msg)
if err == nil {
stakingRequest := msg.GetStaking()
txs := types.Transactions{}
if err = rlp.DecodeBytes(stakingRequest.Transaction, &txs); err == nil {
utils.GetLogInstance().Error("Successfully added staking transaction to pending list.")
utils.GetLogInstance().Info("Successfully added staking transaction to pending list.")
node.addPendingTransactions(txs)
} else {
utils.GetLogInstance().Error("Failed to unmarshal staking transaction list", "error", err)
@ -286,10 +286,12 @@ func (node *Node) VerifyNewBlock(newBlock *types.Block) bool {
// 1. add the new block to blockchain
// 2. [leader] send new block to the client
func (node *Node) PostConsensusProcessing(newBlock *types.Block) {
// if node.Role == BeaconLeader || node.Role == BeaconValidator {
// utils.GetLogInstance().Info("PostConsensusProcessing")
// node.UpdateStakingList(newBlock)
// }
utils.GetLogInstance().Info("PostConsensusProcessing")
if node.Role == BeaconLeader {
utils.GetLogInstance().Info("Updating staking list")
node.UpdateStakingList(newBlock)
node.printStakingList()
}
if node.Consensus.IsLeader {
node.BroadcastNewBlock(newBlock)
}

@ -47,8 +47,8 @@ func (node *Node) WaitForConsensusReady(readySignal chan struct{}, stopChan chan
threshold = FirstTimeThreshold
firstTime = false
}
utils.GetLogInstance().Debug("Proposing New Block...", "threshold", threshold, "pendingTransactions", len(node.pendingTransactions))
if len(node.pendingTransactions) >= threshold {
utils.GetLogInstance().Debug("PROPOSING NEW BLOCK ------------------------------------------------", "threshold", threshold, "pendingTransactions", len(node.pendingTransactions))
// Normal tx block consensus
selectedTxs := node.getTransactionsForNewBlock(MaxNumberOfTransactionsPerBlock)
if len(selectedTxs) != 0 {

@ -3,6 +3,8 @@ package node
import (
"os"
"github.com/harmony-one/harmony/api/service/staking"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
@ -14,7 +16,6 @@ import (
"github.com/harmony-one/harmony/api/service/explorer"
"github.com/harmony-one/harmony/api/service/networkinfo"
"github.com/harmony-one/harmony/api/service/randomness"
"github.com/harmony-one/harmony/api/service/staking"
"github.com/harmony-one/harmony/crypto/pki"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/node/worker"
@ -80,7 +81,7 @@ func (node *Node) setupForNewNode() {
nodeConfig, chanPeer := node.initNodeConfiguration()
// Register staking service.
node.serviceManager.RegisterService(service.Staking, staking.New(node.host, node.AccountKey, 0, node.beaconChain))
node.serviceManager.RegisterService(service.Staking, staking.New(node.host, node.AccountKey, node.beaconChain))
// Register peer discovery service. "0" is the beacon shard ID
node.serviceManager.RegisterService(service.PeerDiscovery, discovery.New(node.host, nodeConfig, chanPeer, node.AddBeaconPeer))
// Register networkinfo service. "0" is the beacon shard ID

@ -1,7 +1,14 @@
package node
import (
"crypto/ecdsa"
"math/big"
"os"
"github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/harmony/internal/utils/contract"
"github.com/harmony-one/harmony/internal/utils"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/harmony-one/harmony/core/types"
@ -13,7 +20,8 @@ import (
//Refer: https://solidity.readthedocs.io/en/develop/abi-spec.html
const (
depositFuncSignature = "0xd0e30db0"
// DepositFuncSignature is the func signature for deposit method
DepositFuncSignature = "0xd0e30db0"
withdrawFuncSignature = "0x2e1a7d4d"
funcSingatureBytes = 4
)
@ -27,13 +35,14 @@ func (node *Node) UpdateStakingList(block *types.Block) error {
txn := txns[i]
toAddress := txn.To()
if toAddress != nil && *toAddress != node.StakingContractAddress { //Not a address aimed at the staking contract.
utils.GetLogInstance().Info("Mismatched Staking Contract Address", "expected", node.StakingContractAddress.Hex(), "got", toAddress.Hex())
continue
}
currentSender, _ := types.Sender(signerType, txn)
_, isPresent := node.CurrentStakes[currentSender]
data := txn.Data()
switch funcSignature := decodeFuncSign(data); funcSignature {
case depositFuncSignature: //deposit, currently: 0xd0e30db0
case DepositFuncSignature: //deposit, currently: 0xd0e30db0
amount := txn.Value()
value := amount.Int64()
if isPresent {
@ -63,6 +72,16 @@ func (node *Node) UpdateStakingList(block *types.Block) error {
return nil
}
func (node *Node) printStakingList() {
utils.GetLogInstance().Info("\n")
utils.GetLogInstance().Info("CURRENT STAKING INFO [START] ------------------------------------")
for addr, stake := range node.CurrentStakes {
utils.GetLogInstance().Info("", "Address", addr, "Stake", stake)
}
utils.GetLogInstance().Info("CURRENT STAKING INFO [END} ------------------------------------")
utils.GetLogInstance().Info("\n")
}
//The first four bytes of the call data for a function call specifies the function to be called.
//It is the first (left, high-order in big-endian) four bytes of the Keccak-256 (SHA-3)
//Refer: https://solidity.readthedocs.io/en/develop/abi-spec.html
@ -80,3 +99,36 @@ func decodeFuncSign(data []byte) string {
funcSign := hexutil.Encode(data[:funcSingatureBytes]) //The function signature is first 4 bytes of data in ethereum
return funcSign
}
// LoadStakingKeyFromFile load staking private key from keyfile
// If the private key is not loadable or no file, it will generate
// a new random private key
// Currently for deploy_newnode.sh, we hard-coded the first fake account as staking account and
// it is minted in genesis block. See genesis_node.go
func LoadStakingKeyFromFile(keyfile string) *ecdsa.PrivateKey {
// contract.FakeAccounts[0] gets minted tokens in genesis block of beacon chain.
key, err := crypto.HexToECDSA(contract.FakeAccounts[0].Private)
if err != nil {
utils.GetLogInstance().Error("Unable to get staking key")
os.Exit(1)
}
if err := crypto.SaveECDSA(keyfile, key); err != nil {
utils.GetLogInstance().Error("Unable to save the private key", "error", err)
os.Exit(1)
}
// TODO(minhdoan): Enable this back.
// key, err := crypto.LoadECDSA(keyfile)
// if err != nil {
// GetLogInstance().Error("no key file. Let's create a staking private key")
// key, err = crypto.GenerateKey()
// if err != nil {
// GetLogInstance().Error("Unable to generate the private key")
// os.Exit(1)
// }
// if err = crypto.SaveECDSA(keyfile, key); err != nil {
// GetLogInstance().Error("Unable to save the private key", "error", err)
// os.Exit(1)
// }
// }
return key
}

@ -130,10 +130,13 @@ $DRYRUN $ROOT/bin/bootnode -port 19876 > $log_folder/bootnode.log 2>&1 | tee -a
sleep 1
BN_MA=$(grep "BN_MA" $log_folder/bootnode.log | awk -F\= ' { print $2 } ')
HMY_OPT2=" -bootnodes $BN_MA"
echo "bootnode launched." + " $BN_MA"
HMY_OPT3=" -is_beacon"
NUM_NN=0
sleep 2
# Start nodes
while IFS='' read -r line || [[ -n "$line" ]]; do
IFS=' ' read ip port mode shardID <<< $line

@ -115,6 +115,7 @@ mkdir -p $log_folder
LOG_FILE=$log_folder/r.log
HMY_OPT=
# Change to the beacon chain output from deploy.sh
HMY_OPT2=
HMY_OPT3=

Loading…
Cancel
Save