Add CrossLink, EIP155, and S3 fork

pull/1493/head
Rongjian Lan 5 years ago
parent 0292e7cdd6
commit 2d51ba0ee2
  1. 8
      cmd/client/wallet/main.go
  2. 8
      cmd/client/wallet_stress_test/main.go
  3. 2
      core/block_validator.go
  4. 2
      core/blockchain.go
  5. 4
      core/chain_makers.go
  6. 32
      core/genesis.go
  7. 6
      core/state_processor.go
  8. 3
      core/state_transition.go
  9. 2
      core/types/transaction_signing.go
  10. 18
      core/vm/evm.go
  11. 8
      core/vm/gas_table.go
  12. 4
      core/vm/instructions.go
  13. 2
      core/vm/interpreter.go
  14. 7
      core/vm/runtime/runtime.go
  15. 9
      core/vm/runtime/runtime_test.go
  16. 2
      internal/chain/engine.go
  17. 3
      internal/keystore/keystore.go
  18. 280
      internal/params/config.go
  19. 36
      internal/params/config_test.go
  20. 43
      internal/params/gas_table.go
  21. 3
      node/node.go
  22. 4
      node/node_genesis.go
  23. 4
      node/node_handler_test.go
  24. 119
      node/node_newblock.go
  25. 2
      node/service_setup.go
  26. 10
      node/staking_test.go
  27. 64
      node/worker/worker.go
  28. 8
      test/chain/main.go

@ -13,6 +13,8 @@ import (
"sync"
"time"
"github.com/harmony-one/harmony/internal/params"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
ffi_bls "github.com/harmony-one/bls/ffi/go/bls"
@ -744,7 +746,11 @@ func processTransferCommand() {
fmt.Printf("Unlock account succeeded! '%v'\n", senderPass)
tx, err = ks.SignTx(account, tx, nil)
chainConfig := params.MainnetChainConfig
if walletProfile.Profile != defaultProfile {
chainConfig = params.TestnetChainConfig
}
tx, err = ks.SignTx(account, tx, chainConfig.ChainID)
if err != nil {
fmt.Printf("SignTx Error: %v\n", err)
return

@ -11,6 +11,8 @@ import (
"sync"
"time"
"github.com/harmony-one/harmony/internal/params"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/harmony-one/harmony/accounts"
@ -286,7 +288,11 @@ func processStressTestCommand() {
ks.Unlock(account, senderPass)
tx, _ = ks.SignTx(account, tx, nil)
chainConfig := params.MainnetChainConfig
if walletProfile.Profile != defaultProfile {
chainConfig = params.TestnetChainConfig
}
tx, _ = ks.SignTx(account, tx, chainConfig.ChainID)
if err := submitTransaction(tx, walletNode, uint32(shardID)); err != nil {
fmt.Println(ctxerror.New("submitTransaction failed",

@ -103,7 +103,7 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
// Validate the state root against the received state root and throw
// an error if they don't match.
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
if root := statedb.IntermediateRoot(v.config.IsS3(header.Number)); header.Root != root {
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
}
return nil

@ -1003,7 +1003,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
rawdb.WriteBlock(bc.db, block)
root, err := state.Commit(bc.chainConfig.IsEIP158(block.Number()))
root, err := state.Commit(bc.chainConfig.IsS3(block.Number()))
if err != nil {
return NonStatTy, err
}

@ -182,7 +182,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
// Write state changes to db
root, err := statedb.Commit(config.IsEIP158(b.header.Number))
root, err := statedb.Commit(config.IsS3(b.header.Number))
if err != nil {
panic(fmt.Sprintf("state write error: %v", err))
}
@ -215,7 +215,7 @@ func makeHeader(chain consensus_engine.ChainReader, parent *types.Block, state *
}
return &types.Header{
Root: state.IntermediateRoot(chain.Config().IsEIP158(parent.Number())),
Root: state.IntermediateRoot(chain.Config().IsS3(parent.Number())),
ParentHash: parent.Hash(),
Coinbase: parent.Coinbase(),
//Difficulty: engine.CalcDifficulty(chain, time.Uint64(), &types.Header{

@ -155,7 +155,7 @@ func (e *GenesisMismatchError) Error() string {
// The returned chain configuration is never nil.
func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
if genesis != nil && genesis.Config == nil {
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
return params.AllProtocolChanges, common.Hash{}, errGenesisNoConfig
}
// Just commit the new block if there is no stored genesis block.
@ -217,7 +217,7 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
case ghash == params.TestnetGenesisHash:
return params.TestnetChainConfig
default:
return params.AllEthashProtocolChanges
return params.AllProtocolChanges
}
}
@ -286,7 +286,7 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
config := g.Config
if config == nil {
config = params.AllEthashProtocolChanges
config = params.AllProtocolChanges
}
rawdb.WriteChainConfig(db, block.Hash(), config)
return block, nil
@ -319,32 +319,6 @@ func DefaultGenesisBlock() *Genesis {
}
}
// DeveloperGenesisBlock returns the 'geth --dev' genesis block. Note, this must
// be seeded with the
func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
// Override the default period to the user requested one
config := *params.AllCliqueProtocolChanges
config.Clique.Period = period
// Assemble and return the genesis with the precompiles and faucet pre-funded
return &Genesis{
Config: &config,
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, 65)...),
GasLimit: 6283185,
Alloc: map[common.Address]GenesisAccount{
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
//faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
},
}
}
func decodePrealloc(data string) GenesisAlloc {
var p []struct{ Addr, Balance *big.Int }

@ -141,10 +141,10 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
}
// Update the state with pending changes
var root []byte
if config.IsByzantium(header.Number) {
if config.IsS3(header.Number) {
statedb.Finalise(true)
} else {
root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
root = statedb.IntermediateRoot(config.IsS3(header.Number)).Bytes()
}
*usedGas += gas
@ -188,7 +188,7 @@ func ApplyIncomingReceipt(config *params.ChainConfig, db *state.DB, header *type
db.CreateAccount(*cx.To)
}
db.AddBalance(*cx.To, cx.Amount)
db.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
db.IntermediateRoot(config.IsS3(header.Number)).Bytes()
}
return nil
}

@ -169,6 +169,7 @@ func (st *StateTransition) preCheck() error {
// Make sure this transaction's nonce is correct.
if st.msg.CheckNonce() {
nonce := st.state.GetNonce(st.msg.From())
if nonce < st.msg.Nonce() {
return ErrNonceTooHigh
} else if nonce > st.msg.Nonce() {
@ -187,7 +188,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
}
msg := st.msg
sender := vm.AccountRef(msg.From())
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
homestead := st.evm.ChainConfig().IsS3(st.evm.BlockNumber) // s3 includes homestead
contractCreation := msg.To() == nil
// Pay intrinsic gas

@ -45,8 +45,6 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
switch {
case config.IsEIP155(blockNumber):
signer = NewEIP155Signer(config.ChainID)
case config.IsHomestead(blockNumber):
signer = HomesteadSigner{}
default:
signer = FrontierSigner{}
}

@ -46,7 +46,7 @@ type (
func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) {
if contract.CodeAddr != nil {
precompiles := PrecompiledContractsHomestead
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
if evm.ChainConfig().IsS3(evm.BlockNumber) {
precompiles = PrecompiledContractsByzantium
}
if p := precompiles[*contract.CodeAddr]; p != nil {
@ -143,7 +143,7 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
interpreters: make([]Interpreter, 0, 1),
}
if chainConfig.IsEWASM(ctx.BlockNumber) {
//if chainConfig.IsS3(ctx.BlockNumber) {
// to be implemented by EVM-C and Wagon PRs.
// if vmConfig.EWASMInterpreter != "" {
// extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":")
@ -156,8 +156,8 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
// } else {
// evm.interpreters = append(evm.interpreters, NewEWASMInterpreter(evm, vmConfig))
// }
panic("No supported ewasm interpreter yet.")
}
// panic("No supported ewasm interpreter yet.")
//}
// vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here
// as we always want to have the built-in EVM as the failover option.
@ -210,10 +210,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
)
if !evm.StateDB.Exist(addr) {
precompiles := PrecompiledContractsHomestead
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
if evm.ChainConfig().IsS3(evm.BlockNumber) {
precompiles = PrecompiledContractsByzantium
}
if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
if precompiles[addr] == nil && evm.ChainConfig().IsS3(evm.BlockNumber) && value.Sign() == 0 {
// Calling a non existing account, don't do anything, but ping the tracer
if evm.vmConfig.Debug && evm.depth == 0 {
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
@ -403,7 +403,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// Create a new account on the state
snapshot := evm.StateDB.Snapshot()
evm.StateDB.CreateAccount(address)
if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
if evm.ChainConfig().IsEIP155(evm.BlockNumber) {
evm.StateDB.SetNonce(address, 1)
}
evm.Transfer(evm.StateDB, caller.Address(), address, value, types.SameShardTx)
@ -426,7 +426,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
ret, err := run(evm, contract, nil, false)
// check whether the max code size has been exceeded
maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize
maxCodeSizeExceeded := evm.ChainConfig().IsEIP155(evm.BlockNumber) && len(ret) > params.MaxCodeSize
// if the contract creation ran successfully and no errors were returned
// calculate the gas required to store the code. If the code could not
// be stored due to not enough gas set an error and let it be handled
@ -443,7 +443,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsS3(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
evm.StateDB.RevertToSnapshot(snapshot)
if err != errExecutionReverted {
contract.UseGas(contract.Gas)

@ -123,7 +123,7 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
// The legacy gas metering only takes into consideration the current state
// Legacy rules should be applied if we are in Petersburg (removal of EIP-1283)
// OR Constantinople is not active
if evm.chainRules.IsPetersburg || !evm.chainRules.IsConstantinople {
if evm.chainRules.IsS3 {
// This checks for 3 scenario's and calculates gas accordingly:
//
// 1. From a zero-value address to a non-zero value (NEW VALUE)
@ -393,7 +393,7 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
gas = gt.Calls
transfersValue = stack.Back(2).Sign() != 0
address = common.BigToAddress(stack.Back(1))
eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber)
eip158 = evm.ChainConfig().IsS3(evm.BlockNumber)
)
if eip158 {
if transfersValue && evm.StateDB.Empty(address) {
@ -459,11 +459,11 @@ func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var gas uint64
// EIP150 homestead gas reprice fork:
if evm.ChainConfig().IsEIP150(evm.BlockNumber) {
if evm.ChainConfig().IsS3(evm.BlockNumber) {
gas = gt.Suicide
var (
address = common.BigToAddress(stack.Back(0))
eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber)
eip158 = evm.ChainConfig().IsS3(evm.BlockNumber)
)
if eip158 {

@ -696,7 +696,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
input = memory.Get(offset.Int64(), size.Int64())
gas = contract.Gas
)
if interpreter.evm.ChainConfig().IsEIP150(interpreter.evm.BlockNumber) {
if interpreter.evm.ChainConfig().IsS3(interpreter.evm.BlockNumber) {
gas -= gas / 64
}
@ -706,7 +706,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
// homestead we must check for CodeStoreOutOfGasError (homestead only
// rule) and treat as an error, if the ruleset is frontier we must
// ignore this error and pretend the operation was successful.
if interpreter.evm.ChainConfig().IsHomestead(interpreter.evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas {
if interpreter.evm.ChainConfig().IsS3(interpreter.evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas {
stack.push(interpreter.intPool.getZero())
} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
stack.push(interpreter.intPool.getZero())

@ -120,7 +120,7 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
}
func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
if in.evm.chainRules.IsByzantium {
if in.evm.chainRules.IsS3 {
if in.readOnly {
// If the interpreter is operating in readonly mode, make sure no
// state-modifying operation is performed. The 3rd stack item

@ -53,12 +53,9 @@ func setDefaults(cfg *Config) {
if cfg.ChainConfig == nil {
cfg.ChainConfig = &params.ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: new(big.Int),
DAOForkBlock: new(big.Int),
DAOForkSupport: false,
EIP150Block: new(big.Int),
CrossLinkBlock: new(big.Int),
EIP155Block: new(big.Int),
EIP158Block: new(big.Int),
S3Block: new(big.Int),
}
}

@ -168,14 +168,9 @@ func benchmarkEVMCreate(bench *testing.B, code string) {
BlockNumber: new(big.Int).SetUint64(1),
ChainConfig: &params.ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: new(big.Int),
ByzantiumBlock: new(big.Int),
ConstantinopleBlock: new(big.Int),
DAOForkBlock: new(big.Int),
DAOForkSupport: false,
EIP150Block: new(big.Int),
CrossLinkBlock: new(big.Int),
EIP155Block: new(big.Int),
EIP158Block: new(big.Int),
S3Block: new(big.Int),
},
EVMConfig: vm.Config{},
}

@ -165,7 +165,7 @@ func (e *engineImpl) Finalize(chain engine.ChainReader, header *types.Header, st
if err := AccumulateRewards(chain, state, header); err != nil {
return nil, ctxerror.New("cannot pay block reward").WithCause(err)
}
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
header.Root = state.IntermediateRoot(chain.Config().IsS3(header.Number))
return types.NewBlock(header, txs, receipts, outcxs, incxs), nil
}

@ -2,6 +2,7 @@ package keystore
import (
"fmt"
"math/big"
"sync"
"github.com/harmony-one/harmony/accounts"
@ -42,7 +43,7 @@ func Unlock(account accounts.Account) {
// SignTx signs transaction using account key
func SignTx(account accounts.Account, tx *types.Transaction) (*types.Transaction, error) {
if hmyKeystore != nil {
return hmyKeystore.SignTx(account, tx, nil)
return hmyKeystore.SignTx(account, tx, big.NewInt(1)) // TODO: use chainID from config
}
return tx, fmt.Errorf("un-initialized keystore")
}

@ -9,143 +9,33 @@ import (
// Genesis hashes to enforce below configs on.
var (
MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
TestnetGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")
RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
MainnetGenesisHash = common.HexToHash("0x")
TestnetGenesisHash = common.HexToHash("0x")
)
// TrustedCheckpoints associates each known checkpoint with the genesis hash of
// the chain it belongs to.
var TrustedCheckpoints = map[common.Hash]*TrustedCheckpoint{
MainnetGenesisHash: MainnetTrustedCheckpoint,
TestnetGenesisHash: TestnetTrustedCheckpoint,
RinkebyGenesisHash: RinkebyTrustedCheckpoint,
GoerliGenesisHash: GoerliTrustedCheckpoint,
}
var (
// MainnetChainConfig is the chain parameters to run a node on the main network.
MainnetChainConfig = &ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(1150000),
DAOForkBlock: big.NewInt(1920000),
DAOForkSupport: true,
EIP150Block: big.NewInt(2463000),
EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
EIP155Block: big.NewInt(2675000),
EIP158Block: big.NewInt(2675000),
ByzantiumBlock: big.NewInt(4370000),
ConstantinopleBlock: big.NewInt(7280000),
PetersburgBlock: big.NewInt(7280000),
Ethash: new(EthashConfig),
}
// MainnetTrustedCheckpoint contains the light client trusted checkpoint for the main network.
MainnetTrustedCheckpoint = &TrustedCheckpoint{
Name: "mainnet",
SectionIndex: 227,
SectionHead: common.HexToHash("0xa2e0b25d72c2fc6e35a7f853cdacb193b4b4f95c606accf7f8fa8415283582c7"),
CHTRoot: common.HexToHash("0xf69bdd4053b95b61a27b106a0e86103d791edd8574950dc96aa351ab9b9f1aa0"),
BloomRoot: common.HexToHash("0xec1b454d4c6322c78ccedf76ac922a8698c3cac4d98748a84af4995b7bd3d744"),
CrossLinkBlock: big.NewInt(589824), // 36 * 2^14
EIP155Block: big.NewInt(589824), // 36 * 2^14
S3Block: big.NewInt(589824), // 36 * 2^14
}
// TestnetChainConfig contains the chain parameters to run a node on the Ropsten test network.
// TestnetChainConfig contains the chain parameters to run a node on the harmony test network.
TestnetChainConfig = &ChainConfig{
ChainID: big.NewInt(3),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: true,
EIP150Block: big.NewInt(0),
EIP150Hash: common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"),
EIP155Block: big.NewInt(10),
EIP158Block: big.NewInt(10),
ByzantiumBlock: big.NewInt(1700000),
ConstantinopleBlock: big.NewInt(4230000),
PetersburgBlock: big.NewInt(4939394),
Ethash: new(EthashConfig),
}
// TestnetTrustedCheckpoint contains the light client trusted checkpoint for the Ropsten test network.
TestnetTrustedCheckpoint = &TrustedCheckpoint{
Name: "testnet",
SectionIndex: 161,
SectionHead: common.HexToHash("0x5378afa734e1feafb34bcca1534c4d96952b754579b96a4afb23d5301ecececc"),
CHTRoot: common.HexToHash("0x1cf2b071e7443a62914362486b613ff30f60cea0d9c268ed8c545f876a3ee60c"),
BloomRoot: common.HexToHash("0x5ac25c84bd18a9cbe878d4609a80220f57f85037a112644532412ba0d498a31b"),
}
// RinkebyChainConfig contains the chain parameters to run a node on the Rinkeby test network.
RinkebyChainConfig = &ChainConfig{
ChainID: big.NewInt(4),
HomesteadBlock: big.NewInt(1),
DAOForkBlock: nil,
DAOForkSupport: true,
EIP150Block: big.NewInt(2),
EIP150Hash: common.HexToHash("0x9b095b36c15eaf13044373aef8ee0bd3a382a5abb92e402afa44b8249c3a90e9"),
EIP155Block: big.NewInt(3),
EIP158Block: big.NewInt(3),
ByzantiumBlock: big.NewInt(1035301),
ConstantinopleBlock: big.NewInt(3660663),
PetersburgBlock: big.NewInt(4321234),
Clique: &CliqueConfig{
Period: 15,
Epoch: 30000,
},
}
// RinkebyTrustedCheckpoint contains the light client trusted checkpoint for the Rinkeby test network.
RinkebyTrustedCheckpoint = &TrustedCheckpoint{
Name: "rinkeby",
SectionIndex: 125,
SectionHead: common.HexToHash("0x8a738386f6bb34add15846f8f49c4c519a2f32519096e792b9f43bcb407c831c"),
CHTRoot: common.HexToHash("0xa1e5720a9bad4dce794f129e4ac6744398197b652868011486a6f89c8ec84a75"),
BloomRoot: common.HexToHash("0xa3048fe8b7e30f77f11bc755a88478363d7d3e71c2bdfe4e8ab9e269cd804ba2"),
}
// GoerliChainConfig contains the chain parameters to run a node on the Görli test network.
GoerliChainConfig = &ChainConfig{
ChainID: big.NewInt(5),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: true,
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
Clique: &CliqueConfig{
Period: 15,
Epoch: 30000,
},
}
// GoerliTrustedCheckpoint contains the light client trusted checkpoint for the Görli test network.
GoerliTrustedCheckpoint = &TrustedCheckpoint{
Name: "goerli",
SectionIndex: 9,
SectionHead: common.HexToHash("0x8e223d827391eee53b07cb8ee057dbfa11c93e0b45352188c783affd7840a921"),
CHTRoot: common.HexToHash("0xe0a817ac69b36c1e437c5b0cff9e764853f5115702b5f66d451b665d6afb7e78"),
BloomRoot: common.HexToHash("0x50d672aeb655b723284969c7c1201fb6ca003c23ed144bcb9f2d1b30e2971c1b"),
ChainID: big.NewInt(2),
CrossLinkBlock: big.NewInt(0), // 36 * 2^14
EIP155Block: big.NewInt(0), // 36 * 2^14
S3Block: big.NewInt(0), // 36 * 2^14
}
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Ethash consensus.
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus.
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
// AllProtocolChanges ...
AllProtocolChanges = &ChainConfig{big.NewInt(100), big.NewInt(0), big.NewInt(0), big.NewInt(0)}
// TestChainConfig ...
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}
TestChainConfig = &ChainConfig{big.NewInt(99), big.NewInt(0), big.NewInt(0), big.NewInt(0)}
// TestRules ...
TestRules = TestChainConfig.Rules(new(big.Int))
)
@ -170,26 +60,10 @@ type TrustedCheckpoint struct {
type ChainConfig struct {
ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead)
DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` // TheDAO hard-fork switch block (nil = no fork)
DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
CrossLinkBlock *big.Int `json:"homesteadBlock,omitempty"`
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
EIP150Hash common.Hash `json:"eip150Hash,omitempty"` // EIP150 HF hash (needed for header only clients as only gas pricing changed)
EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block
ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium)
ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople)
EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated)
// Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty"`
Clique *CliqueConfig `json:"clique,omitempty"`
EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block (include EIP158 too)
S3Block *big.Int `json:"s3Block,omitempty"` // S3 block is the first block containing S3 mainnet and all ethereum update up to Constantinople
}
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
@ -213,75 +87,26 @@ func (c *CliqueConfig) String() string {
// String implements the fmt.Stringer interface.
func (c *ChainConfig) String() string {
var engine interface{}
switch {
case c.Ethash != nil:
engine = c.Ethash
case c.Clique != nil:
engine = c.Clique
default:
engine = "unknown"
}
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v ConstantinopleFix: %v Engine: %v}",
return fmt.Sprintf("{ChainID: %v EIP155: %v CrossLink: %v}",
c.ChainID,
c.HomesteadBlock,
c.DAOForkBlock,
c.DAOForkSupport,
c.EIP150Block,
c.CrossLinkBlock,
c.EIP155Block,
c.EIP158Block,
c.ByzantiumBlock,
c.ConstantinopleBlock,
c.PetersburgBlock,
engine,
)
}
// IsHomestead returns whether num is either equal to the homestead block or greater.
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
return isForked(c.HomesteadBlock, num)
}
// IsDAOFork returns whether num is either equal to the DAO fork block or greater.
func (c *ChainConfig) IsDAOFork(num *big.Int) bool {
return isForked(c.DAOForkBlock, num)
}
// IsEIP150 returns whether num is either equal to the EIP150 fork block or greater.
func (c *ChainConfig) IsEIP150(num *big.Int) bool {
return isForked(c.EIP150Block, num)
}
// IsEIP155 returns whether num is either equal to the EIP155 fork block or greater.
func (c *ChainConfig) IsEIP155(num *big.Int) bool {
return isForked(c.EIP155Block, num)
}
// IsEIP158 returns whether num is either equal to the EIP158 fork block or greater.
func (c *ChainConfig) IsEIP158(num *big.Int) bool {
return isForked(c.EIP158Block, num)
}
// IsByzantium returns whether num is either equal to the Byzantium fork block or greater.
func (c *ChainConfig) IsByzantium(num *big.Int) bool {
return isForked(c.ByzantiumBlock, num)
}
// IsConstantinople returns whether num is either equal to the Constantinople fork block or greater.
func (c *ChainConfig) IsConstantinople(num *big.Int) bool {
return isForked(c.ConstantinopleBlock, num)
// IsCrossLink returns whether num is either equal to the CrossLink fork block or greater.
func (c *ChainConfig) IsCrossLink(num *big.Int) bool {
return isForked(c.CrossLinkBlock, num)
}
// IsPetersburg returns whether num is either
// - equal to or greater than the PetersburgBlock fork block,
// - OR is nil, and Constantinople is active
func (c *ChainConfig) IsPetersburg(num *big.Int) bool {
return isForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isForked(c.ConstantinopleBlock, num)
}
// IsEWASM returns whether num represents a block number after the EWASM fork
func (c *ChainConfig) IsEWASM(num *big.Int) bool {
return isForked(c.EWASMBlock, num)
// IsS3 returns whether num is either equal to the S3 fork block or greater.
func (c *ChainConfig) IsS3(num *big.Int) bool {
return isForked(c.CrossLinkBlock, num)
}
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
@ -289,17 +114,13 @@ func (c *ChainConfig) IsEWASM(num *big.Int) bool {
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
func (c *ChainConfig) GasTable(num *big.Int) GasTable {
if num == nil {
return GasTableHomestead
return GasTableR3
}
switch {
case c.IsConstantinople(num):
return GasTableConstantinople
case c.IsEIP158(num):
return GasTableEIP158
case c.IsEIP150(num):
return GasTableEIP150
case c.IsS3(num):
return GasTableS3
default:
return GasTableHomestead
return GasTableR3
}
}
@ -322,38 +143,14 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *Confi
}
func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *ConfigCompatError {
if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) {
return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock)
}
if isForkIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, head) {
return newCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock)
}
if c.IsDAOFork(head) && c.DAOForkSupport != newcfg.DAOForkSupport {
return newCompatError("DAO fork support flag", c.DAOForkBlock, newcfg.DAOForkBlock)
}
if isForkIncompatible(c.EIP150Block, newcfg.EIP150Block, head) {
return newCompatError("EIP150 fork block", c.EIP150Block, newcfg.EIP150Block)
}
if isForkIncompatible(c.EIP155Block, newcfg.EIP155Block, head) {
return newCompatError("EIP155 fork block", c.EIP155Block, newcfg.EIP155Block)
}
if isForkIncompatible(c.EIP158Block, newcfg.EIP158Block, head) {
return newCompatError("EIP158 fork block", c.EIP158Block, newcfg.EIP158Block)
}
if c.IsEIP158(head) && !configNumEqual(c.ChainID, newcfg.ChainID) {
return newCompatError("EIP158 chain ID", c.EIP158Block, newcfg.EIP158Block)
}
if isForkIncompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, head) {
return newCompatError("Byzantium fork block", c.ByzantiumBlock, newcfg.ByzantiumBlock)
}
if isForkIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, head) {
return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock)
}
if isForkIncompatible(c.PetersburgBlock, newcfg.PetersburgBlock, head) {
return newCompatError("ConstantinopleFix fork block", c.PetersburgBlock, newcfg.PetersburgBlock)
if isForkIncompatible(c.CrossLinkBlock, newcfg.CrossLinkBlock, head) {
return newCompatError("CrossLink fork block", c.CrossLinkBlock, newcfg.CrossLinkBlock)
}
if isForkIncompatible(c.EWASMBlock, newcfg.EWASMBlock, head) {
return newCompatError("ewasm fork block", c.EWASMBlock, newcfg.EWASMBlock)
if isForkIncompatible(c.S3Block, newcfg.S3Block, head) {
return newCompatError("S3 fork block", c.S3Block, newcfg.S3Block)
}
return nil
}
@ -420,8 +217,7 @@ func (err *ConfigCompatError) Error() string {
// phases.
type Rules struct {
ChainID *big.Int
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
IsByzantium, IsConstantinople, IsPetersburg bool
IsCrossLink, IsEIP155, IsS3 bool
}
// Rules ensures c's ChainID is not nil.
@ -432,12 +228,8 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
}
return Rules{
ChainID: new(big.Int).Set(chainID),
IsHomestead: c.IsHomestead(num),
IsEIP150: c.IsEIP150(num),
IsCrossLink: c.IsCrossLink(num),
IsEIP155: c.IsEIP155(num),
IsEIP158: c.IsEIP158(num),
IsByzantium: c.IsByzantium(num),
IsConstantinople: c.IsConstantinople(num),
IsPetersburg: c.IsPetersburg(num),
IsS3: c.IsS3(num),
}
}

@ -13,42 +13,20 @@ func TestCheckCompatible(t *testing.T) {
wantErr *ConfigCompatError
}
tests := []test{
{stored: AllEthashProtocolChanges, new: AllEthashProtocolChanges, head: 0, wantErr: nil},
{stored: AllEthashProtocolChanges, new: AllEthashProtocolChanges, head: 100, wantErr: nil},
{stored: AllProtocolChanges, new: AllProtocolChanges, head: 0, wantErr: nil},
{stored: AllProtocolChanges, new: AllProtocolChanges, head: 100, wantErr: nil},
{
stored: &ChainConfig{EIP150Block: big.NewInt(10)},
new: &ChainConfig{EIP150Block: big.NewInt(20)},
stored: &ChainConfig{EIP155Block: big.NewInt(10)},
new: &ChainConfig{EIP155Block: big.NewInt(20)},
head: 9,
wantErr: nil,
},
{
stored: AllEthashProtocolChanges,
new: &ChainConfig{HomesteadBlock: nil},
head: 3,
wantErr: &ConfigCompatError{
What: "Homestead fork block",
StoredConfig: big.NewInt(0),
NewConfig: nil,
RewindTo: 0,
},
},
{
stored: AllEthashProtocolChanges,
new: &ChainConfig{HomesteadBlock: big.NewInt(1)},
head: 3,
wantErr: &ConfigCompatError{
What: "Homestead fork block",
StoredConfig: big.NewInt(0),
NewConfig: big.NewInt(1),
RewindTo: 0,
},
},
{
stored: &ChainConfig{HomesteadBlock: big.NewInt(30), EIP150Block: big.NewInt(10)},
new: &ChainConfig{HomesteadBlock: big.NewInt(25), EIP150Block: big.NewInt(20)},
stored: &ChainConfig{S3Block: big.NewInt(30), EIP155Block: big.NewInt(10)},
new: &ChainConfig{S3Block: big.NewInt(25), EIP155Block: big.NewInt(20)},
head: 25,
wantErr: &ConfigCompatError{
What: "EIP150 fork block",
What: "EIP155 fork block",
StoredConfig: big.NewInt(10),
NewConfig: big.NewInt(20),
RewindTo: 9,

@ -1,6 +1,6 @@
package params
// GasTable organizes gas prices for different ethereum phases.
// GasTable organizes gas prices for different harmony phases.
type GasTable struct {
ExtcodeSize uint64
ExtcodeCopy uint64
@ -20,11 +20,11 @@ type GasTable struct {
CreateBySuicide uint64
}
// Variables containing gas prices for different ethereum phases.
// Variables containing gas prices for different harmony phases.
var (
// GasTableHomestead contain the gas prices for
// the homestead phase.
GasTableHomestead = GasTable{
// GasTableR3 contain the gas prices for
// the r3 phase.
GasTableR3 = GasTable{
ExtcodeSize: 20,
ExtcodeCopy: 20,
Balance: 20,
@ -33,36 +33,9 @@ var (
Suicide: 0,
ExpByte: 10,
}
// GasTableEIP150 contain the gas re-prices for
// the EIP150 phase.
GasTableEIP150 = GasTable{
ExtcodeSize: 700,
ExtcodeCopy: 700,
Balance: 400,
SLoad: 200,
Calls: 700,
Suicide: 5000,
ExpByte: 10,
CreateBySuicide: 25000,
}
// GasTableEIP158 contain the gas re-prices for
// the EIP155/EIP158 phase.
GasTableEIP158 = GasTable{
ExtcodeSize: 700,
ExtcodeCopy: 700,
Balance: 400,
SLoad: 200,
Calls: 700,
Suicide: 5000,
ExpByte: 50,
CreateBySuicide: 25000,
}
// GasTableConstantinople contain the gas re-prices for
// the constantinople phase.
GasTableConstantinople = GasTable{
// GasTableS3 contain the gas re-prices for
// the s3 phase.
GasTableS3 = GasTable{
ExtcodeSize: 700,
ExtcodeCopy: 700,
ExtcodeHash: 400,

@ -3,7 +3,6 @@ package node
import (
"crypto/ecdsa"
"fmt"
"math/big"
"sync"
"time"
@ -370,8 +369,6 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, chainDBFactory shardc
if node.NodeConfig.GetNetworkType() == nodeconfig.Mainnet {
chainConfig = *params.MainnetChainConfig
}
// TODO: use 1 as mainnet, change to networkID instead
chainConfig.ChainID = big.NewInt(1)
collection := shardchain.NewCollection(
chainDBFactory, &genesisInitializer{&node}, chain.Engine, &chainConfig)

@ -88,10 +88,6 @@ func (node *Node) SetupGenesisBlock(db ethdb.Database, shardID uint32, myShardSt
node.ContractDeployerKey = contractDeployerKey
}
// Initialize shard state
// TODO: use 1 for now as mainnet, change to networkID instead
chainConfig.ChainID = big.NewInt(1)
gspec := core.Genesis{
Config: &chainConfig,
Alloc: genesisAlloc,

@ -32,7 +32,7 @@ func TestAddNewBlock(t *testing.T) {
selectedTxs := node.getTransactionsForNewBlock(common.Address{})
node.Worker.CommitTransactions(selectedTxs, common.Address{})
block, _ := node.Worker.Commit([]byte{}, []byte{}, 0, common.Address{})
block, _ := node.Worker.FinalizeNewBlock([]byte{}, []byte{}, 0, common.Address{}, nil, nil)
err = node.AddNewBlock(block)
if err != nil {
@ -61,7 +61,7 @@ func TestVerifyNewBlock(t *testing.T) {
selectedTxs := node.getTransactionsForNewBlock(common.Address{})
node.Worker.CommitTransactions(selectedTxs, common.Address{})
block, _ := node.Worker.Commit([]byte{}, []byte{}, 0, common.Address{})
block, _ := node.Worker.FinalizeNewBlock([]byte{}, []byte{}, 0, common.Address{}, nil, nil)
if err := node.VerifyNewBlock(block); err != nil {
t.Error("New block is not verified successfully:", err)

@ -7,7 +7,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/internal/ctxerror"
@ -19,20 +18,19 @@ const (
PeriodicBlock = 200 * time.Millisecond
)
// WaitForConsensusReadyv2 listen for the readiness signal from consensus and generate new block for consensus.
// WaitForConsensusReadyV2 listen for the readiness signal from consensus and generate new block for consensus.
// only leader will receive the ready signal
// TODO: clean pending transactions for validators; or validators not prepare pending transactions
func (node *Node) WaitForConsensusReadyv2(readySignal chan struct{}, stopChan chan struct{}, stoppedChan chan struct{}) {
func (node *Node) WaitForConsensusReadyV2(readySignal chan struct{}, stopChan chan struct{}, stoppedChan chan struct{}) {
go func() {
// Setup stoppedChan
defer close(stoppedChan)
utils.Logger().Debug().
Msg("Waiting for Consensus ready")
// TODO: make local net start faster
time.Sleep(30 * time.Second) // Wait for other nodes to be ready (test-only)
var newBlock *types.Block
// Set up the very first deadline.
deadline := time.Now().Add(node.BlockPeriod)
for {
@ -49,38 +47,49 @@ func (node *Node) WaitForConsensusReadyv2(readySignal chan struct{}, stopChan ch
continue
}
coinbase := node.Consensus.SelfAddress
if err := node.Worker.UpdateCurrent(coinbase); err != nil {
utils.Logger().Error().
Err(err).
Msg("Failed updating worker's state")
continue
utils.Logger().Debug().
Uint64("blockNum", node.Blockchain().CurrentBlock().NumberU64()+1).
Msg("=========Proposing New Block==========")
newBlock, err := node.proposeNewBlock()
if err == nil {
utils.Logger().Debug().
Uint64("blockNum", newBlock.NumberU64()).
Int("numTxs", newBlock.Transactions().Len()).
Int("crossShardReceipts", newBlock.IncomingReceipts().Len()).
Msg("=========Successfully Proposed New Block==========")
// Set deadline will be BlockPeriod from now at this place. Announce stage happens right after this.
deadline = time.Now().Add(node.BlockPeriod)
// Send the new block to Consensus so it can be confirmed.
node.BlockChannel <- newBlock
break
} else {
utils.Logger().Err(err).
Msg("!!!!!!!!!cannot commit new block!!!!!!!!!")
}
}
}
}
}()
}
// Normal tx block consensus
func (node *Node) proposeNewBlock() (*types.Block, error) {
// Update worker's current header and state data in preparation to propose/process new transactions
coinbase := node.Consensus.SelfAddress
// Prepare transactions
selectedTxs := node.getTransactionsForNewBlock(coinbase)
if err := node.Worker.UpdateCurrent(coinbase); err != nil {
utils.GetLogger().Error("Failed updating worker's state", "Error", err)
}
utils.Logger().Info().
Uint64("blockNum", node.Blockchain().CurrentBlock().NumberU64()+1).
Int("selectedTxs", len(selectedTxs)).
Msg("PROPOSING NEW BLOCK ------------------------------------------------")
if err := node.Worker.CommitTransactions(selectedTxs, coinbase); err != nil {
ctxerror.Log15(utils.GetLogger().Error,
ctxerror.New("cannot commit transactions").
WithCause(err))
}
sig, mask, err := node.Consensus.LastCommitSig()
if err != nil {
ctxerror.Log15(utils.GetLogger().Error,
ctxerror.New("Cannot got commit signatures from last block").
WithCause(err))
continue
return nil, err
}
// Propose cross shard receipts
// Prepare cross shard transaction receipts
receiptsList := node.proposeReceiptsProof()
if len(receiptsList) != 0 {
if err := node.Worker.CommitReceipts(receiptsList); err != nil {
@ -90,64 +99,38 @@ func (node *Node) WaitForConsensusReadyv2(readySignal chan struct{}, stopChan ch
}
}
viewID := node.Consensus.GetViewID()
// add aggregated commit signatures from last block, except for the first two blocks
// Prepare cross links
var crossLinks types.CrossLinks
if node.NodeConfig.ShardID == 0 {
crossLinksToPropose, localErr := node.ProposeCrossLinkDataForBeaconchain()
if localErr == nil {
data, localErr := rlp.EncodeToBytes(crossLinksToPropose)
if localErr == nil {
newBlock, err = node.Worker.CommitWithCrossLinks(sig, mask, viewID, coinbase, data)
utils.Logger().Debug().
Uint64("blockNum", newBlock.NumberU64()).
Int("numCrossLinks", len(crossLinksToPropose)).
Msg("Successfully added cross links into new block")
crossLinks = crossLinksToPropose
} else {
utils.Logger().Debug().Err(localErr).Msg("ops0 ProposeCrossLinkDataForBeaconchain Failed")
utils.Logger().Debug().Err(localErr).Msg("Failed to propose cross links")
}
} else {
utils.Logger().Debug().Err(localErr).Msg("ops1 ProposeCrossLinkDataForBeaconchain Failed")
newBlock, err = node.Worker.Commit(sig, mask, viewID, coinbase)
}
} else {
newBlock, err = node.Worker.Commit(sig, mask, viewID, coinbase)
}
// Prepare shard state
shardState := node.Worker.ProposeShardStateWithoutBeaconSync()
// Prepare last commit signatures
sig, mask, err := node.Consensus.LastCommitSig()
if err != nil {
ctxerror.Log15(utils.GetLogger().Error,
ctxerror.New("cannot commit new block").
ctxerror.New("Cannot get commit signatures from last block").
WithCause(err))
continue
} else if err := node.proposeShardStateWithoutBeaconSync(newBlock); err != nil {
ctxerror.Log15(utils.GetLogger().Error,
ctxerror.New("cannot add shard state").
WithCause(err))
} else {
utils.Logger().Debug().
Uint64("blockNum", newBlock.NumberU64()).
Int("numTxs", newBlock.Transactions().Len()).
Msg("Successfully proposed new block")
// Set deadline will be BlockPeriod from now at this place. Announce stage happens right after this.
deadline = time.Now().Add(node.BlockPeriod)
// Send the new block to Consensus so it can be confirmed.
node.BlockChannel <- newBlock
break
}
}
}
return nil, err
}
}()
return node.Worker.FinalizeNewBlock(sig, mask, node.Consensus.GetViewID(), coinbase, crossLinks, shardState)
}
func (node *Node) proposeShardStateWithoutBeaconSync(block *types.Block) error {
func (node *Node) proposeShardStateWithoutBeaconSync(block *types.Block) types.ShardState {
if block == nil || !core.IsEpochLastBlock(block) {
return nil
}
nextEpoch := new(big.Int).Add(block.Header().Epoch, common.Big1)
shardState := core.GetShardState(nextEpoch)
return block.AddShardState(shardState)
return core.GetShardState(nextEpoch)
}
func (node *Node) proposeShardState(block *types.Block) error {

@ -26,7 +26,7 @@ func (node *Node) setupForValidator() {
// Register consensus service.
node.serviceManager.RegisterService(service.Consensus, consensus.New(node.BlockChannel, node.Consensus, node.startConsensus))
// Register new block service.
node.serviceManager.RegisterService(service.BlockProposal, blockproposal.New(node.Consensus.ReadySignal, node.WaitForConsensusReadyv2))
node.serviceManager.RegisterService(service.BlockProposal, blockproposal.New(node.Consensus.ReadySignal, node.WaitForConsensusReadyV2))
// Register client support service.
node.serviceManager.RegisterService(service.ClientSupport, clientsupport.New(node.Blockchain().State, node.CallFaucetContract, node.getDeployedStakingContract, node.SelfPeer.IP, node.SelfPeer.Port))
// Register new metrics service

@ -40,12 +40,16 @@ func TestUpdateStakingList(t *testing.T) {
node := New(host, consensus, testDBFactory, false)
node.BlockPeriod = 8 * time.Second
for i := 0; i < 5; i++ {
for i := 0; i < 1; i++ {
selectedTxs := node.getTransactionsForNewBlock(common.Address{})
node.Worker.CommitTransactions(selectedTxs, common.Address{})
block, _ := node.Worker.Commit([]byte{}, []byte{}, 0, common.Address{})
block, err := node.Worker.FinalizeNewBlock([]byte{}, []byte{}, 0, common.Address{}, nil, nil)
err := node.AddNewBlock(block)
if err != nil {
t.Errorf("Error when finalizing block: %v", err)
}
block.Header()
err = node.AddNewBlock(block)
if err != nil {
t.Errorf("Error when adding new block: %v", err)
}

@ -5,6 +5,8 @@ import (
"math/big"
"time"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/harmony/internal/params"
@ -85,6 +87,14 @@ func (w *Worker) throttleTxs(selected types.Transactions, recentTxsStats types.R
// SelectTransactionsForNewBlock selects transactions for new block.
func (w *Worker) SelectTransactionsForNewBlock(newBlockNum uint64, txs types.Transactions, recentTxsStats types.RecentTxsStats, txsThrottleConfig *shardingconfig.TxsThrottleConfig, coinbase common.Address) (types.Transactions, types.Transactions, types.Transactions) {
// Must update to the correct current state before processing potential txns
if err := w.UpdateCurrent(coinbase); err != nil {
utils.Logger().Error().
Err(err).
Msg("Failed updating worker's state before txn selection")
return types.Transactions{}, txs, types.Transactions{}
}
if w.current.gasPool == nil {
w.current.gasPool = new(core.GasPool).AddGas(w.current.header.GasLimit)
}
@ -158,6 +168,14 @@ func (w *Worker) commitTransaction(tx *types.Transaction, coinbase common.Addres
// CommitTransactions commits transactions.
func (w *Worker) CommitTransactions(txs types.Transactions, coinbase common.Address) error {
// Must update to the correct current state before processing potential txns
if err := w.UpdateCurrent(coinbase); err != nil {
utils.Logger().Error().
Err(err).
Msg("Failed updating worker's state before committing txns")
return err
}
if w.current.gasPool == nil {
w.current.gasPool = new(core.GasPool).AddGas(w.current.header.GasLimit)
}
@ -258,8 +276,17 @@ func (w *Worker) IncomingReceipts() []*types.CXReceiptsProof {
return w.current.incxs
}
// CommitWithCrossLinks generate a new block with cross links for the new txs.
func (w *Worker) CommitWithCrossLinks(sig []byte, signers []byte, viewID uint64, coinbase common.Address, crossLinks []byte) (*types.Block, error) {
// ProposeShardStateWithoutBeaconSync proposes the next shard state for next epoch.
func (w *Worker) ProposeShardStateWithoutBeaconSync() types.ShardState {
if !core.ShardingSchedule.IsLastBlock(w.current.header.Number.Uint64()) {
return nil
}
nextEpoch := new(big.Int).Add(w.current.header.Epoch, common.Big1)
return core.GetShardState(nextEpoch)
}
// FinalizeNewBlock generate a new block for the next consensus round.
func (w *Worker) FinalizeNewBlock(sig []byte, signers []byte, viewID uint64, coinbase common.Address, crossLinks types.CrossLinks, shardState types.ShardState) (*types.Block, error) {
if len(sig) > 0 && len(signers) > 0 {
copy(w.current.header.LastCommitSignature[:], sig[:])
w.current.header.LastCommitBitmap = append(signers[:0:0], signers...)
@ -267,7 +294,33 @@ func (w *Worker) CommitWithCrossLinks(sig []byte, signers []byte, viewID uint64,
w.current.header.Coinbase = coinbase
w.current.header.ViewID = new(big.Int)
w.current.header.ViewID.SetUint64(viewID)
w.current.header.CrossLinks = crossLinks
// Cross Links
if crossLinks != nil && len(crossLinks) != 0 {
crossLinkData, err := rlp.EncodeToBytes(crossLinks)
if err == nil {
utils.Logger().Debug().
Uint64("blockNum", w.current.header.Number.Uint64()).
Int("numCrossLinks", len(crossLinks)).
Msg("Successfully proposed cross links into new block")
w.current.header.CrossLinks = crossLinkData
} else {
utils.Logger().Debug().Err(err).Msg("Failed to encode proposed cross links")
return nil, err
}
}
// Shard State
if shardState != nil && len(shardState) != 0 {
w.current.header.ShardStateHash = shardState.Hash()
shardStateData, err := rlp.EncodeToBytes(shardState)
if err == nil {
w.current.header.ShardState = shardStateData
} else {
utils.Logger().Debug().Err(err).Msg("Failed to encode proposed shard state")
return nil, err
}
}
s := w.current.state.Copy()
@ -279,11 +332,6 @@ func (w *Worker) CommitWithCrossLinks(sig []byte, signers []byte, viewID uint64,
return block, nil
}
// Commit generate a new block for the new txs.
func (w *Worker) Commit(sig []byte, signers []byte, viewID uint64, coinbase common.Address) (*types.Block, error) {
return w.CommitWithCrossLinks(sig, signers, viewID, coinbase, []byte{})
}
// New create a new worker object.
func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus_engine.Engine, shardID uint32) *Worker {
worker := &Worker{

@ -128,7 +128,7 @@ func fundFaucetContract(chain *core.BlockChain) {
if err != nil {
fmt.Println(err)
}
block, _ := contractworker.Commit([]byte{}, []byte{}, 0, common.Address{})
block, _ := contractworker.FinalizeNewBlock([]byte{}, []byte{}, 0, common.Address{}, nil, nil)
_, err = chain.InsertChain(types.Blocks{block})
if err != nil {
fmt.Println(err)
@ -169,7 +169,7 @@ func callFaucetContractToFundAnAddress(chain *core.BlockChain) {
if err != nil {
fmt.Println(err)
}
block, _ := contractworker.Commit([]byte{}, []byte{}, 0, common.Address{})
block, _ := contractworker.FinalizeNewBlock([]byte{}, []byte{}, 0, common.Address{}, nil, nil)
_, err = chain.InsertChain(types.Blocks{block})
if err != nil {
fmt.Println(err)
@ -245,7 +245,7 @@ func playStaking(chain *core.BlockChain) {
if err != nil {
fmt.Println(err)
}
block, _ := contractworker.Commit([]byte{}, []byte{}, 0, common.Address{})
block, _ := contractworker.FinalizeNewBlock([]byte{}, []byte{}, 0, common.Address{}, nil, nil)
_, err = chain.InsertChain(types.Blocks{block})
if err != nil {
fmt.Println(err)
@ -304,7 +304,7 @@ func playWithdrawStaking(chain *core.BlockChain) {
fmt.Println(err)
}
block, _ := contractworker.Commit([]byte{}, []byte{}, 0, common.Address{})
block, _ := contractworker.FinalizeNewBlock([]byte{}, []byte{}, 0, common.Address{}, nil, nil)
_, err = chain.InsertChain(types.Blocks{block})
if err != nil {
fmt.Println(err)

Loading…
Cancel
Save