Merge pull request #547 from harmony-one/rj_branch

setup initial beacon chain keys
pull/548/head
Rongjian Lan 6 years ago committed by GitHub
commit dfb0053b6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      cmd/harmony/main.go
  2. 2
      core/blockchain.go
  3. 4
      core/rawdb/accessors_chain.go
  4. 3
      core/resharding.go
  5. 18
      internal/utils/contract/constants.go
  6. 14
      node/contract.go
  7. 1
      node/node.go
  8. 30
      node/node_genesis.go
  9. 12
      node/staking.go
  10. 10
      test/configs/beaconchain.txt

@ -9,6 +9,8 @@ import (
"runtime" "runtime"
"time" "time"
"github.com/harmony-one/harmony/internal/utils/contract"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/harmony-one/harmony/consensus" "github.com/harmony-one/harmony/consensus"
@ -119,18 +121,28 @@ func createGlobalConfig() *nodeconfig.ConfigType {
// Currently we hardcode only one shard. // Currently we hardcode only one shard.
nodeConfig.ShardIDString = "0" nodeConfig.ShardIDString = "0"
nodeConfig.StakingPriKey = node.LoadStakingKeyFromFile(*stakingKeyFile, *accountIndex) // Key Setup ================= [Start]
// Staking private key is the ecdsa key used for token related transaction signing (especially the staking txs).
stakingPriKey := ""
if *isBeacon {
stakingPriKey = contract.InitialBeaconChainAccounts[*accountIndex].Private
} else {
stakingPriKey = contract.NewNodeAccounts[*accountIndex].Private
}
nodeConfig.StakingPriKey = node.StoreStakingKeyFromFile(*stakingKeyFile, stakingPriKey)
// P2p private key is used for secure message transfer between p2p nodes.
nodeConfig.P2pPriKey, _, err = utils.LoadKeyFromFile(*keyFile) nodeConfig.P2pPriKey, _, err = utils.LoadKeyFromFile(*keyFile)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// Setup Bls keys // Consensus keys are the BLS12-381 keys used to sign consensus messages
nodeConfig.ConsensusPriKey, nodeConfig.ConsensusPubKey = utils.GenKey(*ip, *port) nodeConfig.ConsensusPriKey, nodeConfig.ConsensusPubKey = utils.GenKey(*ip, *port)
if nodeConfig.ConsensusPriKey == nil || nodeConfig.ConsensusPubKey == nil { if nodeConfig.ConsensusPriKey == nil || nodeConfig.ConsensusPubKey == nil {
panic(fmt.Errorf("generate key error")) panic(fmt.Errorf("generate key error"))
} }
// Key Setup ================= [End]
// Initialize leveldb for main blockchain and beacon. // Initialize leveldb for main blockchain and beacon.
if nodeConfig.MainDB, err = InitLDBDatabase(*ip, *port, *freshDB, false); err != nil { if nodeConfig.MainDB, err = InitLDBDatabase(*ip, *port, *freshDB, false); err != nil {

@ -1653,7 +1653,7 @@ func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscript
return bc.scope.Track(bc.logsFeed.Subscribe(ch)) return bc.scope.Track(bc.logsFeed.Subscribe(ch))
} }
// GetShardState retrives sharding state given block hash and block number // GetShardState retrieves sharding state given block hash and block number
func (bc *BlockChain) GetShardState(hash common.Hash, number uint64) types.ShardState { func (bc *BlockChain) GetShardState(hash common.Hash, number uint64) types.ShardState {
if cached, ok := bc.shardStateCache.Get(hash); ok { if cached, ok := bc.shardStateCache.Get(hash); ok {
shardState := cached.(types.ShardState) shardState := cached.(types.ShardState)

@ -374,7 +374,7 @@ func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header {
return a return a
} }
// ReadShardState retrieves sharding state // ReadShardState retrieves sharding state.
func ReadShardState(db DatabaseReader, hash common.Hash, number uint64) types.ShardState { func ReadShardState(db DatabaseReader, hash common.Hash, number uint64) types.ShardState {
data, _ := db.Get(shardStateKey(number, hash)) data, _ := db.Get(shardStateKey(number, hash))
if len(data) == 0 { if len(data) == 0 {
@ -388,7 +388,7 @@ func ReadShardState(db DatabaseReader, hash common.Hash, number uint64) types.Sh
return shardState return shardState
} }
// WriteShardState stores sharding state into database // WriteShardState stores sharding state into database.
func WriteShardState(db DatabaseWriter, hash common.Hash, number uint64, shardState types.ShardState) { func WriteShardState(db DatabaseWriter, hash common.Hash, number uint64, shardState types.ShardState) {
data, err := rlp.EncodeToBytes(shardState) data, err := rlp.EncodeToBytes(shardState)
if err != nil { if err != nil {

@ -86,6 +86,7 @@ func (ss *ShardingState) assignLeaders() {
func (ss *ShardingState) UpdateShardState(newNodeList []types.NodeID, percent float64) { func (ss *ShardingState) UpdateShardState(newNodeList []types.NodeID, percent float64) {
rand.Seed(int64(ss.rnd)) rand.Seed(int64(ss.rnd))
ss.sortCommitteeBySize() ss.sortCommitteeBySize()
// TODO: separate shuffling and leader assignment
ss.assignLeaders() ss.assignLeaders()
ss.assignNewNodes(newNodeList) ss.assignNewNodes(newNodeList)
ss.cuckooResharding(percent) ss.cuckooResharding(percent)
@ -124,7 +125,7 @@ func GetShardingStateFromBlockChain(bc *BlockChain, epoch uint64) *ShardingState
return &ShardingState{epoch: epoch, rnd: rndSeed, shardState: shardState, numShards: len(shardState)} return &ShardingState{epoch: epoch, rnd: rndSeed, shardState: shardState, numShards: len(shardState)}
} }
// CalculateNewShardState get sharding state from previous epoch and calcualte sharding state for new epoch // CalculateNewShardState get sharding state from previous epoch and calculate sharding state for new epoch
// TODO: currently, we just mock everything // TODO: currently, we just mock everything
func CalculateNewShardState(bc *BlockChain, epoch uint64) types.ShardState { func CalculateNewShardState(bc *BlockChain, epoch uint64) types.ShardState {
if epoch == FirstEpoch { if epoch == FirstEpoch {

@ -38,18 +38,8 @@ 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. // InitialBeaconChainAccounts are the accounts for the initial beacon chain node.
var StakingAccounts = [...]DeployAccount{ var InitialBeaconChainAccounts = [...]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"}, {Address: "0xE2bD4413172C98d5094B94de1A8AC6a383d68b84", Private: "e401343197a852f361e38ce6b46c99f1d6d1f80499864c6ae7effee42b46ab6b", Public: "0xE2bD4413172C98d5094B94de1A8AC6a383d68b84"},
{Address: "0x183418934Fd8A97c98E086151317B2df6259b8A8", Private: "a7d764439a7619f703c97ee2a2cf0be2cd62ad4c9deebd5423d6f28de417b907", Public: "0x183418934Fd8A97c98E086151317B2df6259b8A8"}, {Address: "0x183418934Fd8A97c98E086151317B2df6259b8A8", Private: "a7d764439a7619f703c97ee2a2cf0be2cd62ad4c9deebd5423d6f28de417b907", Public: "0x183418934Fd8A97c98E086151317B2df6259b8A8"},
{Address: "0x9df0e70D4cb3E9beC0548D8Ac56F46596D1BcdB6", Private: "4e3f7c819a15249d2824834cd7ce20fe24d6eab8eb39ac63b78cb3713362cf78", Public: "0x9df0e70D4cb3E9beC0548D8Ac56F46596D1BcdB6"}, {Address: "0x9df0e70D4cb3E9beC0548D8Ac56F46596D1BcdB6", Private: "4e3f7c819a15249d2824834cd7ce20fe24d6eab8eb39ac63b78cb3713362cf78", Public: "0x9df0e70D4cb3E9beC0548D8Ac56F46596D1BcdB6"},
@ -60,6 +50,10 @@ var FakeAccounts = [...]DeployAccount{
{Address: "0x6f7659765a8784F782fc6Bcdb153e915076bb9F0", Private: "24be53d408b360cc1a3608d54fa8ba070692bbe8f594062c30a5e9e89cee9794", Public: "0x6f7659765a8784F782fc6Bcdb153e915076bb9F0"}, {Address: "0x6f7659765a8784F782fc6Bcdb153e915076bb9F0", Private: "24be53d408b360cc1a3608d54fa8ba070692bbe8f594062c30a5e9e89cee9794", Public: "0x6f7659765a8784F782fc6Bcdb153e915076bb9F0"},
{Address: "0xfA24E616BaE95160878C7F1150d1e014904809E9", Private: "41d628799eee7637bd79ae9fc2fd1321cffbb4b858348d6abf5b4247b78fd492", Public: "0xfA24E616BaE95160878C7F1150d1e014904809E9"}, {Address: "0xfA24E616BaE95160878C7F1150d1e014904809E9", Private: "41d628799eee7637bd79ae9fc2fd1321cffbb4b858348d6abf5b4247b78fd492", Public: "0xfA24E616BaE95160878C7F1150d1e014904809E9"},
{Address: "0x47DF74d43fa4Ca1D814897eBD8Cf07e6bA024f75", Private: "d5a62757aa51f2ae883c5cb8631d312750ecc31f3934fffd95bcd969bd190c94", Public: "0x47DF74d43fa4Ca1D814897eBD8Cf07e6bA024f75"}, {Address: "0x47DF74d43fa4Ca1D814897eBD8Cf07e6bA024f75", Private: "d5a62757aa51f2ae883c5cb8631d312750ecc31f3934fffd95bcd969bd190c94", Public: "0x47DF74d43fa4Ca1D814897eBD8Cf07e6bA024f75"},
}
// NewNodeAccounts is the accounts used for new node to stake and join the network.
var NewNodeAccounts = [...]DeployAccount{
{Address: "0x1a3e7a44ee21101d7D64FBf29B0F6F1fc295F723", Private: "27978f895b11d9c737e1ab1623fde722c04b4f9ccb4ab776bf15932cc72d7c66", Public: "0x1a3e7a44ee21101d7D64FBf29B0F6F1fc295F723"}, {Address: "0x1a3e7a44ee21101d7D64FBf29B0F6F1fc295F723", Private: "27978f895b11d9c737e1ab1623fde722c04b4f9ccb4ab776bf15932cc72d7c66", Public: "0x1a3e7a44ee21101d7D64FBf29B0F6F1fc295F723"},
{Address: "0x10A02A0a6e95a676AE23e2db04BEa3D1B8b7ca2E", Private: "371cb68abe6a6101ac88603fc847e0c013a834253acee5315884d2c4e387ebca", Public: "0x10A02A0a6e95a676AE23e2db04BEa3D1B8b7ca2E"}, {Address: "0x10A02A0a6e95a676AE23e2db04BEa3D1B8b7ca2E", Private: "371cb68abe6a6101ac88603fc847e0c013a834253acee5315884d2c4e387ebca", Public: "0x10A02A0a6e95a676AE23e2db04BEa3D1B8b7ca2E"},
{Address: "0x3e881F6C36A3A14a2D1816b0A5471d1caBB16F33", Private: "3f8af52063c6648be37d4b33559f784feb16d8e5ffaccf082b3657ea35b05977", Public: "0x3e881F6C36A3A14a2D1816b0A5471d1caBB16F33"}, {Address: "0x3e881F6C36A3A14a2D1816b0A5471d1caBB16F33", Private: "3f8af52063c6648be37d4b33559f784feb16d8e5ffaccf082b3657ea35b05977", Public: "0x3e881F6C36A3A14a2D1816b0A5471d1caBB16F33"},

@ -16,7 +16,6 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/internal/utils/contract"
contract_constants "github.com/harmony-one/harmony/internal/utils/contract" contract_constants "github.com/harmony-one/harmony/internal/utils/contract"
) )
@ -158,16 +157,3 @@ func (node *Node) callGetFreeTokenWithNonce(address common.Address, nonce uint64
node.addPendingTransactions(types.Transactions{tx}) node.addPendingTransactions(types.Transactions{tx})
return tx.Hash() return tx.Hash()
} }
// 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.callGetFreeTokenWithNonce(address, nonce+uint64(i))
}
}

@ -254,7 +254,6 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, db ethdb.Database) *N
node.AddFaucetContractToPendingTransactions() node.AddFaucetContractToPendingTransactions()
node.CurrentStakes = make(map[common.Address]*big.Int) node.CurrentStakes = make(map[common.Address]*big.Int)
node.AddStakingContractToPendingTransactions() //This will save the latest information about staked nodes in current staked node.AddStakingContractToPendingTransactions() //This will save the latest information about staked nodes in current staked
node.DepositToStakingAccounts()
} }
node.ContractCaller = contracts.NewContractCaller(&db, node.blockchain, params.TestChainConfig) node.ContractCaller = contracts.NewContractCaller(&db, node.blockchain, params.TestChainConfig)

@ -6,6 +6,9 @@ import (
"math/rand" "math/rand"
"strings" "strings"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/internal/utils/contract"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -16,14 +19,17 @@ import (
const ( const (
// FakeAddressNumber is the number of fake address. // FakeAddressNumber is the number of fake address.
FakeAddressNumber = 100 FakeAddressNumber = 100
// TotalInitFund is the initial total fund to the faucet. // TotalInitFund is the initial total fund for the contract deployer.
TotalInitFund = 9000000 TotalInitFund = 9000000
) )
// GenesisBlockSetup setups a genesis blockchain. // GenesisBlockSetup setups a genesis blockchain.
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
// Tests account for txgen to use
genesisAlloc := node.CreateGenesisAllocWithTestingAddresses(FakeAddressNumber) genesisAlloc := node.CreateGenesisAllocWithTestingAddresses(FakeAddressNumber)
// Smart contract deployer account used to deploy protocol-level smart contract
contractDeployerKey, _ := 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"))
contractDeployerAddress := crypto.PubkeyToAddress(contractDeployerKey.PublicKey) contractDeployerAddress := crypto.PubkeyToAddress(contractDeployerKey.PublicKey)
contractDeployerFunds := big.NewInt(TotalInitFund) contractDeployerFunds := big.NewInt(TotalInitFund)
@ -31,6 +37,9 @@ func (node *Node) GenesisBlockSetup(db ethdb.Database) (*core.BlockChain, error)
genesisAlloc[contractDeployerAddress] = core.GenesisAccount{Balance: contractDeployerFunds} genesisAlloc[contractDeployerAddress] = core.GenesisAccount{Balance: contractDeployerFunds}
node.ContractDeployerKey = contractDeployerKey node.ContractDeployerKey = contractDeployerKey
// Accounts used by validator/nodes to stake and participate in the network.
AddNodeAddressesToGenesisAlloc(genesisAlloc)
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
gspec := core.Genesis{ gspec := core.Genesis{
@ -45,7 +54,7 @@ func (node *Node) GenesisBlockSetup(db ethdb.Database) (*core.BlockChain, error)
} }
// CreateGenesisAllocWithTestingAddresses create the genesis block allocation that contains deterministically // CreateGenesisAllocWithTestingAddresses create the genesis block allocation that contains deterministically
// generated testing addressess with tokens. // generated testing addressess with tokens. This is mostly used for generated simulated transactions in txgen.
// TODO: Remove it later when moving to production. // TODO: Remove it later when moving to production.
func (node *Node) CreateGenesisAllocWithTestingAddresses(numAddress int) core.GenesisAlloc { func (node *Node) CreateGenesisAllocWithTestingAddresses(numAddress int) core.GenesisAlloc {
rand.Seed(0) rand.Seed(0)
@ -66,3 +75,20 @@ func (node *Node) CreateGenesisAllocWithTestingAddresses(numAddress int) core.Ge
} }
return genesisAloc return genesisAloc
} }
// AddNodeAddressesToGenesisAlloc adds to the genesis block allocation the accounts used for network validators/nodes,
// including the account used by the nodes of the initial beacon chain and later new nodes.
func AddNodeAddressesToGenesisAlloc(genesisAlloc core.GenesisAlloc) {
for _, account := range contract.InitialBeaconChainAccounts {
testBankFunds := big.NewInt(100)
testBankFunds = testBankFunds.Mul(testBankFunds, big.NewInt(params.Ether))
address := common.HexToAddress(account.Address)
genesisAlloc[address] = core.GenesisAccount{Balance: testBankFunds}
}
for _, account := range contract.NewNodeAccounts {
testBankFunds := big.NewInt(100)
testBankFunds = testBankFunds.Mul(testBankFunds, big.NewInt(params.Ether))
address := common.HexToAddress(account.Address)
genesisAlloc[address] = core.GenesisAccount{Balance: testBankFunds}
}
}

@ -9,8 +9,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/harmony-one/harmony/internal/utils/contract"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@ -84,14 +82,10 @@ func decodeFuncSign(data []byte) string {
return funcSign return funcSign
} }
// LoadStakingKeyFromFile load staking private key from keyfile // StoreStakingKeyFromFile load the staking private key and store it in local keyfile
// If the private key is not loadable or no file, it will generate func StoreStakingKeyFromFile(keyfile string, priKey string) *ecdsa.PrivateKey {
// 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, accountIndex int) *ecdsa.PrivateKey {
// contract.FakeAccounts[0] gets minted tokens in genesis block of beacon chain. // contract.FakeAccounts[0] gets minted tokens in genesis block of beacon chain.
key, err := crypto.HexToECDSA(contract.StakingAccounts[accountIndex].Private) key, err := crypto.HexToECDSA(priKey)
if err != nil { if err != nil {
utils.GetLogInstance().Error("Unable to get staking key") utils.GetLogInstance().Error("Unable to get staking key")
os.Exit(1) os.Exit(1)

@ -0,0 +1,10 @@
127.0.0.1 9000 leader 0
127.0.0.1 9001 validator 0
127.0.0.1 9002 validator 0
127.0.0.1 9003 validator 0
127.0.0.1 9004 validator 0
127.0.0.1 9005 validator 0
127.0.0.1 9006 validator 0
127.0.0.1 9007 validator 0
127.0.0.1 9008 validator 0
127.0.0.1 9009 validator 0
Loading…
Cancel
Save