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 { if err != nil {
utils.GetLogInstance().Error("[DISCOVERY] Failed to send ping message", "group", g) utils.GetLogInstance().Error("[DISCOVERY] Failed to send ping message", "group", g)
} else { } else {
utils.GetLogInstance().Info("[DISCOVERY]", "Sent Ping Message", g) //utils.GetLogInstance().Info("[DISCOVERY]", "Sent Ping Message", g)
} }
} }
} }

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

@ -143,7 +143,7 @@ func main() {
var clientPeer *p2p.Peer var clientPeer *p2p.Peer
var role string var role string
stakingPriKey := utils.LoadStakingKeyFromFile(*stakingKeyFile) stakingPriKey := node.LoadStakingKeyFromFile(*stakingKeyFile)
nodePriKey, _, err := utils.LoadKeyFromFile(*keyFile) nodePriKey, _, err := utils.LoadKeyFromFile(*keyFile)
if err != nil { if err != nil {
@ -180,8 +180,6 @@ func main() {
panic("unable to new host in harmony") 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) host.AddPeer(&leader)
// Consensus object. // Consensus object.
@ -245,6 +243,7 @@ func main() {
} }
// Assign closure functions to the consensus object // Assign closure functions to the consensus object
consensus.BlockVerifier = currentNode.VerifyNewBlock
consensus.OnConsensusDone = currentNode.PostConsensusProcessing consensus.OnConsensusDone = currentNode.PostConsensusProcessing
currentNode.State = node.NodeWaitToJoin currentNode.State = node.NodeWaitToJoin
@ -252,6 +251,7 @@ func main() {
go currentNode.SendPongMessage() 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() go currentNode.SupportSyncing()
currentNode.ServiceManagerSetup() currentNode.ServiceManagerSetup()
currentNode.RunServices() currentNode.RunServices()

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

@ -321,7 +321,7 @@ func (consensus *Consensus) processCommitMessage(message *msg_pb.Message) {
consensus.consensusID++ consensus.consensusID++
consensus.OnConsensusDone(&blockObj) 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 // TODO: remove this temporary delay
time.Sleep(500 * time.Millisecond) 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") utils.GetLogInstance().Debug("failed to construct the new block after consensus")
} }
// check block data (transactions // check block data (transactions
// TODO: change to verify the block body if err := consensus.VerifyHeader(consensus.ChainReader, blockObj.Header(), false); err != nil {
if err := consensus.VerifyHeader(consensus.ChainReader, blockObj.Header(), true); err != nil {
utils.GetLogInstance().Debug("[WARNING] Block content is not verified successfully", "consensusID", consensus.consensusID) utils.GetLogInstance().Debug("[WARNING] Block content is not verified successfully", "consensusID", consensus.consensusID)
return return
} }

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

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

@ -2,7 +2,6 @@ package utils
import ( import (
"bytes" "bytes"
"crypto/ecdsa"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -14,7 +13,6 @@ import (
"strconv" "strconv"
"sync" "sync"
crypto "github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
p2p_crypto "github.com/libp2p/go-libp2p-crypto" 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) key, pk, err = LoadPrivateKey(keyStruct.Key)
return key, pk, err 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" "math/big"
"strings" "strings"
"github.com/harmony-one/harmony/internal/utils"
"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/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -37,7 +39,7 @@ func (node *Node) AddStakingContractToPendingTransactions() {
// Unsigned transaction to avoid the case of transaction address. // 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) 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 = crypto.CreateAddress(contractAddress, uint64(0))
node.StakingContractAddress = node.generateDeployedStakingContractAddress(mycontracttx, contractAddress) node.StakingContractAddress = node.generateDeployedStakingContractAddress(contractAddress)
node.addPendingTransactions(types.Transactions{mycontracttx}) 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) // (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. // 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. // 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 { func (node *Node) generateDeployedStakingContractAddress(contractAddress common.Address) common.Address {
//Ideally we send the transaction to
//Correct Way 1: //Correct Way 1:
//node.SendTx(mycontracttx) //node.SendTx(mycontracttx)
//receipts := node.worker.GetCurrentReceipts() //receipts := node.worker.GetCurrentReceipts()
@ -56,7 +56,6 @@ func (node *Node) generateDeployedStakingContractAddress(mycontracttx *types.Tra
//Correct Way 2: //Correct Way 2:
//nonce := GetNonce(contractAddress) //nonce := GetNonce(contractAddress)
//deployedAddress := crypto.CreateAddress(contractAddress, uint64(nonce)) //deployedAddress := crypto.CreateAddress(contractAddress, uint64(nonce))
//deployedcontractaddress = recepits[len(receipts)-1].ContractAddress //get the address from the receipt
nonce := 0 nonce := 0
return crypto.CreateAddress(contractAddress, uint64(nonce)) return crypto.CreateAddress(contractAddress, uint64(nonce))
} }
@ -97,7 +96,7 @@ func (node *Node) getDeployedStakingContract() common.Address {
// AddFaucetContractToPendingTransactions adds the faucet contract the genesis block. // AddFaucetContractToPendingTransactions adds the faucet contract the genesis block.
func (node *Node) AddFaucetContractToPendingTransactions() { func (node *Node) AddFaucetContractToPendingTransactions() {
// Add a contract deployment transactionv // Add a contract deployment transactionv
priKey := node.ContractKeys[0] priKey := node.ContractDeployerKey
dataEnc := common.FromHex(FaucetContractBinary) dataEnc := common.FromHex(FaucetContractBinary)
// Unsigned transaction to avoid the case of transaction address. // 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 // CallFaucetContract invokes the faucet contract to give the walletAddress initial money
func (node *Node) CallFaucetContract(walletAddress common.Address) common.Hash { func (node *Node) CallFaucetContract(address common.Address) common.Hash {
return node.createSendingMoneyTransaction(walletAddress) 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() state, err := node.blockchain.State()
if err != nil { if err != nil {
log.Error("Failed to get chain state", "Error", err) log.Error("Failed to get chain state", "Error", err)
} }
nonce := state.GetNonce(crypto.PubkeyToAddress(node.ContractKeys[0].PublicKey)) nonce := state.GetNonce(crypto.PubkeyToAddress(node.ContractDeployerKey.PublicKey))
contractData := FaucetFreeMoneyMethodCall + hex.EncodeToString(walletAddress.Bytes()) 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) 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}) node.addPendingTransactions(types.Transactions{tx})
return tx.Hash() return tx.Hash()
} }
// DepositToFakeAccounts invokes the faucet contract to give the walletAddress initial money // DepositToStakingAccounts invokes the faucet contract to give the staking accounts initial money
func (node *Node) DepositToFakeAccounts() { func (node *Node) DepositToStakingAccounts() {
for _, deployAccount := range contract.FakeAccounts { 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) address := common.HexToAddress(deployAccount.Address)
node.createSendingMoneyTransaction(address) node.callGetFreeTokenWithNonce(address, nonce+uint64(i))
} }
} }

@ -58,6 +58,26 @@ const (
ClientNode 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 { func (state State) String() string {
switch state { switch state {
case NodeInit: case NodeInit:
@ -161,7 +181,7 @@ type Node struct {
// For test only // For test only
TestBankKeys []*ecdsa.PrivateKey TestBankKeys []*ecdsa.PrivateKey
ContractKeys []*ecdsa.PrivateKey ContractDeployerKey *ecdsa.PrivateKey
ContractAddresses []common.Address ContractAddresses []common.Address
// Group Message Receiver // Group Message Receiver
@ -205,11 +225,9 @@ func (node *Node) addPendingTransactions(newTxs types.Transactions) {
func (node *Node) getTransactionsForNewBlock(maxNumTxs int) types.Transactions { func (node *Node) getTransactionsForNewBlock(maxNumTxs int) types.Transactions {
node.pendingTxMutex.Lock() node.pendingTxMutex.Lock()
selected, unselected, invalid := node.Worker.SelectTransactionsForNewBlock(node.pendingTransactions, maxNumTxs) 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 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() node.pendingTxMutex.Unlock()
return selected 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.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) 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()) utils.GetLogInstance().Debug("Created Genesis Block", "blockHash", chain.GetBlockByNumber(0).Hash().Hex())
node.Consensus.ConsensusBlock = make(chan *consensus.BFTBlockInfo) node.Consensus.ConsensusBlock = make(chan *consensus.BFTBlockInfo)
node.Consensus.VerifiedNewBlock = make(chan *types.Block) 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 { if consensusObj != nil && consensusObj.IsLeader {

@ -24,18 +24,12 @@ const (
func (node *Node) GenesisBlockSetup(db ethdb.Database) (*core.BlockChain, error) { func (node *Node) GenesisBlockSetup(db ethdb.Database) (*core.BlockChain, error) {
// Initialize genesis block and blockchain // Initialize genesis block and blockchain
genesisAlloc := node.CreateGenesisAllocWithTestingAddresses(FakeAddressNumber) 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")) contractDeployerKey, _ := 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) contractDeployerAddress := crypto.PubkeyToAddress(contractDeployerKey.PublicKey)
contractFunds := big.NewInt(TotalInitFund) contractDeployerFunds := big.NewInt(TotalInitFund)
contractFunds = contractFunds.Mul(contractFunds, big.NewInt(params.Ether)) contractDeployerFunds = contractDeployerFunds.Mul(contractDeployerFunds, big.NewInt(params.Ether))
genesisAlloc[contractAddress] = core.GenesisAccount{Balance: contractFunds} genesisAlloc[contractDeployerAddress] = core.GenesisAccount{Balance: contractDeployerFunds}
node.ContractKeys = append(node.ContractKeys, contractKey) node.ContractDeployerKey = contractDeployerKey
node.AddFaucetContractToPendingTransactions()
if node.Role == BeaconLeader {
node.AddStakingContractToPendingTransactions() //This will save the latest information about staked nodes in current staked
node.DepositToFakeAccounts()
}
chainConfig := params.TestChainConfig chainConfig := params.TestChainConfig
chainConfig.ChainID = big.NewInt(int64(node.Consensus.ShardID)) // Use ChainID as piggybacked ShardID 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 { if node.Role != BeaconLeader {
return return
} }
node.addStakingTxnIntoPendingTxns(msgPayload) node.processStakingMessage(msgPayload)
case proto.Node: case proto.Node:
actionType := proto_node.MessageType(msgType) actionType := proto_node.MessageType(msgType)
switch actionType { 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{} msg := &message.Message{}
err := pb.Unmarshal(msgPayload, msg) err := pb.Unmarshal(msgPayload, msg)
if err == nil { if err == nil {
stakingRequest := msg.GetStaking() stakingRequest := msg.GetStaking()
txs := types.Transactions{} txs := types.Transactions{}
if err = rlp.DecodeBytes(stakingRequest.Transaction, &txs); err == nil { 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) node.addPendingTransactions(txs)
} else { } else {
utils.GetLogInstance().Error("Failed to unmarshal staking transaction list", "error", err) 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 // 1. add the new block to blockchain
// 2. [leader] send new block to the client // 2. [leader] send new block to the client
func (node *Node) PostConsensusProcessing(newBlock *types.Block) { func (node *Node) PostConsensusProcessing(newBlock *types.Block) {
// if node.Role == BeaconLeader || node.Role == BeaconValidator { utils.GetLogInstance().Info("PostConsensusProcessing")
// utils.GetLogInstance().Info("PostConsensusProcessing") if node.Role == BeaconLeader {
// node.UpdateStakingList(newBlock) utils.GetLogInstance().Info("Updating staking list")
// } node.UpdateStakingList(newBlock)
node.printStakingList()
}
if node.Consensus.IsLeader { if node.Consensus.IsLeader {
node.BroadcastNewBlock(newBlock) node.BroadcastNewBlock(newBlock)
} }

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

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

@ -1,7 +1,14 @@
package node package node
import ( import (
"crypto/ecdsa"
"math/big" "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/ethereum/go-ethereum/common/hexutil"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
@ -13,7 +20,8 @@ import (
//Refer: https://solidity.readthedocs.io/en/develop/abi-spec.html //Refer: https://solidity.readthedocs.io/en/develop/abi-spec.html
const ( const (
depositFuncSignature = "0xd0e30db0" // DepositFuncSignature is the func signature for deposit method
DepositFuncSignature = "0xd0e30db0"
withdrawFuncSignature = "0x2e1a7d4d" withdrawFuncSignature = "0x2e1a7d4d"
funcSingatureBytes = 4 funcSingatureBytes = 4
) )
@ -27,13 +35,14 @@ func (node *Node) UpdateStakingList(block *types.Block) error {
txn := txns[i] txn := txns[i]
toAddress := txn.To() toAddress := txn.To()
if toAddress != nil && *toAddress != node.StakingContractAddress { //Not a address aimed at the staking contract. 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 continue
} }
currentSender, _ := types.Sender(signerType, txn) currentSender, _ := types.Sender(signerType, txn)
_, isPresent := node.CurrentStakes[currentSender] _, isPresent := node.CurrentStakes[currentSender]
data := txn.Data() data := txn.Data()
switch funcSignature := decodeFuncSign(data); funcSignature { switch funcSignature := decodeFuncSign(data); funcSignature {
case depositFuncSignature: //deposit, currently: 0xd0e30db0 case DepositFuncSignature: //deposit, currently: 0xd0e30db0
amount := txn.Value() amount := txn.Value()
value := amount.Int64() value := amount.Int64()
if isPresent { if isPresent {
@ -63,6 +72,16 @@ func (node *Node) UpdateStakingList(block *types.Block) error {
return nil 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. //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) //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 //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 funcSign := hexutil.Encode(data[:funcSingatureBytes]) //The function signature is first 4 bytes of data in ethereum
return funcSign 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 sleep 1
BN_MA=$(grep "BN_MA" $log_folder/bootnode.log | awk -F\= ' { print $2 } ') BN_MA=$(grep "BN_MA" $log_folder/bootnode.log | awk -F\= ' { print $2 } ')
HMY_OPT2=" -bootnodes $BN_MA" HMY_OPT2=" -bootnodes $BN_MA"
echo "bootnode launched." + " $BN_MA"
HMY_OPT3=" -is_beacon" HMY_OPT3=" -is_beacon"
NUM_NN=0 NUM_NN=0
sleep 2
# Start nodes # Start nodes
while IFS='' read -r line || [[ -n "$line" ]]; do while IFS='' read -r line || [[ -n "$line" ]]; do
IFS=' ' read ip port mode shardID <<< $line IFS=' ' read ip port mode shardID <<< $line

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

Loading…
Cancel
Save