From 39c80ce175f37117b66ee3e76dd8ca1569dd5d3d Mon Sep 17 00:00:00 2001 From: fudongbai <296179868@qq.com> Date: Sun, 10 May 2020 14:26:15 +0800 Subject: [PATCH 01/12] more strick condition for system transaction --- consensus/parlia/parlia.go | 2 +- eth/api_tracer.go | 28 +++++++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index fe6f0b066f..368f4abfbd 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -265,7 +265,7 @@ func (p *Parlia) IsSystemTransaction(tx *types.Transaction, header *types.Header if err != nil { return false, errors.New("UnAuthorized transaction") } - if sender == header.Coinbase && isToSystemContract(*tx.To()) { + if sender == header.Coinbase && isToSystemContract(*tx.To()) && tx.GasPrice().Cmp(big.NewInt(0)) == 0 { return true, nil } return false, nil diff --git a/eth/api_tracer.go b/eth/api_tracer.go index a08406cb49..7db3327990 100644 --- a/eth/api_tracer.go +++ b/eth/api_tracer.go @@ -502,12 +502,13 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, // Generate the next state snapshot fast without tracing msg, _ := tx.AsMessage(signer) vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) - if posa, ok := api.eth.engine.(consensus.PoSA); ok && msg.From() == block.Header().Coinbase && - posa.IsSystemContract(msg.To()) { - balance := statedb.GetBalance(consensus.SystemAddress) - if balance.Cmp(common.Big0) > 0 { - statedb.SetBalance(consensus.SystemAddress, big.NewInt(0)) - statedb.AddBalance(block.Header().Coinbase, balance) + if posa, ok := api.eth.engine.(consensus.PoSA); ok { + if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem { + balance := statedb.GetBalance(consensus.SystemAddress) + if balance.Cmp(common.Big0) > 0 { + statedb.SetBalance(consensus.SystemAddress, big.NewInt(0)) + statedb.AddBalance(block.Header().Coinbase, balance) + } } } vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{}) @@ -767,7 +768,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v // Run the transaction with tracing enabled. vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{Debug: true, Tracer: tracer}) if posa, ok := api.eth.engine.(consensus.PoSA); ok && message.From() == vmctx.Coinbase && - posa.IsSystemContract(message.To()) { + posa.IsSystemContract(message.To()) && message.GasPrice().Cmp(big.NewInt(0)) == 0 { balance := statedb.GetBalance(consensus.SystemAddress) if balance.Cmp(common.Big0) > 0 { statedb.SetBalance(consensus.SystemAddress, big.NewInt(0)) @@ -822,12 +823,13 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset msg, _ := tx.AsMessage(signer) - if posa, ok := api.eth.engine.(consensus.PoSA); ok && msg.From() == block.Header().Coinbase && - posa.IsSystemContract(msg.To()) { - balance := statedb.GetBalance(consensus.SystemAddress) - if balance.Cmp(common.Big0) > 0 { - statedb.SetBalance(consensus.SystemAddress, big.NewInt(0)) - statedb.AddBalance(block.Header().Coinbase, balance) + if posa, ok := api.eth.engine.(consensus.PoSA); ok { + if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem { + balance := statedb.GetBalance(consensus.SystemAddress) + if balance.Cmp(common.Big0) > 0 { + statedb.SetBalance(consensus.SystemAddress, big.NewInt(0)) + statedb.AddBalance(block.Header().Coinbase, balance) + } } } context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) From 4909842097aa2240ee65b4183ad22f9575fff7d5 Mon Sep 17 00:00:00 2001 From: fudongbai <296179868@qq.com> Date: Wed, 13 May 2020 17:57:53 +0800 Subject: [PATCH 02/12] add gov init transaction --- consensus/parlia/parlia.go | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 368f4abfbd..9072d3d92f 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -54,11 +54,14 @@ const ( systemRewardPercent = 4 // it means 1/2^4 = 1/16 percentage of gas fee incoming will be distributed to system // genesis contracts - ValidatorContract = "0x0000000000000000000000000000000000001000" - SlashContract = "0x0000000000000000000000000000000000001001" - SystemRewardContract = "0x0000000000000000000000000000000000001002" - LightClientContract = "0x0000000000000000000000000000000000001003" - RelayerHubContract = "0x0000000000000000000000000000000000001006" + ValidatorContract = "0x0000000000000000000000000000000000001000" + SlashContract = "0x0000000000000000000000000000000000001001" + SystemRewardContract = "0x0000000000000000000000000000000000001002" + LightClientContract = "0x0000000000000000000000000000000000001003" + TokenHubContract = "0x0000000000000000000000000000000000001004" + RelayerIncentivizeContract = "0x0000000000000000000000000000000000001005" + RelayerHubContract = "0x0000000000000000000000000000000000001006" + GovHubContract = "0x0000000000000000000000000000000000001007" ) var ( @@ -69,11 +72,14 @@ var ( maxSystemBalance = new(big.Int).Mul(big.NewInt(100), big.NewInt(params.Ether)) systemContracts = map[common.Address]bool{ - common.HexToAddress(ValidatorContract): true, - common.HexToAddress(SlashContract): true, - common.HexToAddress(SystemRewardContract): true, - common.HexToAddress(LightClientContract): true, - common.HexToAddress(RelayerHubContract): true, + common.HexToAddress(ValidatorContract): true, + common.HexToAddress(SlashContract): true, + common.HexToAddress(SystemRewardContract): true, + common.HexToAddress(LightClientContract): true, + common.HexToAddress(RelayerHubContract): true, + common.HexToAddress(GovHubContract): true, + common.HexToAddress(TokenHubContract): true, + common.HexToAddress(RelayerIncentivizeContract): true, } ) @@ -975,7 +981,7 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain // method method := "init" // contracts - contracts := []string{ValidatorContract, SlashContract, LightClientContract, RelayerHubContract} + contracts := []string{ValidatorContract, SlashContract, LightClientContract, RelayerHubContract, GovHubContract, TokenHubContract, RelayerIncentivizeContract} // get packed data data, err := p.validatorSetABI.Pack(method) if err != nil { From ed9b28fe7b3e9a4aa47ce74632ca168931881a0a Mon Sep 17 00:00:00 2001 From: fudongbai <296179868@qq.com> Date: Mon, 1 Jun 2020 21:39:21 +0800 Subject: [PATCH 03/12] fix validator failed to sync a block produced by itself --- consensus/parlia/parlia.go | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index fe6f0b066f..dbc5673a7c 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -653,7 +653,7 @@ func (p *Parlia) Finalize(chain consensus.ChainReader, header *types.Header, sta // No block rewards in PoA, so the state remains as is and uncles are dropped cx := chainContext{Chain: chain, parlia: p} if header.Number.Cmp(common.Big1) == 0 { - err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas) + err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false) if err != nil { log.Error("init contract failed") } @@ -674,14 +674,14 @@ func (p *Parlia) Finalize(chain consensus.ChainReader, header *types.Header, sta } if !signedRecently { log.Info("slash validator", "block hash", header.Hash(), "address", spoiledVal) - err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas) + err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false) if err != nil { panic(err) } } } val := header.Coinbase - err := p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas) + err := p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false) if err != nil { panic(err) } @@ -706,7 +706,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainReader, header *types. receipts = make([]*types.Receipt, 0) } if header.Number.Cmp(common.Big1) == 0 { - err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed) + err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true) if err != nil { log.Error("init contract failed") } @@ -726,13 +726,13 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainReader, header *types. } } if !signedRecently { - err = p.slash(spoiledVal, state, header, cx, &txs, &receipts, nil, &header.GasUsed) + err = p.slash(spoiledVal, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true) if err != nil { panic(err) } } } - err := p.distributeIncoming(p.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed) + err := p.distributeIncoming(p.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true) if err != nil { panic(err) } @@ -923,7 +923,7 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash) ([]common.Address, // slash spoiled validators func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { coinbase := header.Coinbase balance := state.GetBalance(consensus.SystemAddress) if balance.Cmp(common.Big0) <= 0 { @@ -937,7 +937,7 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he var rewards = new(big.Int) rewards = rewards.Rsh(balance, systemRewardPercent) if rewards.Cmp(common.Big0) > 0 { - err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas) + err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) if err != nil { return err } @@ -946,12 +946,12 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he } } log.Info("distribute to validator contract", "block hash", header.Hash(), "amount", balance) - return p.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas) + return p.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) } // slash spoiled validators func (p *Parlia) slash(spoiledVal common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { // method method := "slash" @@ -966,12 +966,12 @@ func (p *Parlia) slash(spoiledVal common.Address, state *state.StateDB, header * // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(SlashContract), data, common.Big0) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) } // init contract func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { // method method := "init" // contracts @@ -986,7 +986,7 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0) // apply message log.Info("init contract", "block hash", header.Hash(), "contract", c) - err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas) + err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) if err != nil { return err } @@ -995,17 +995,17 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain } func (p *Parlia) distributeToSystem(amount *big.Int, state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(SystemRewardContract), nil, amount) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) } // slash spoiled validators func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { // method method := "deposit" @@ -1020,7 +1020,7 @@ func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(ValidatorContract), data, amount) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) } // get system message @@ -1043,13 +1043,13 @@ func (p *Parlia) applyTransaction( header *types.Header, chainContext core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, - receivedTxs *[]*types.Transaction, usedGas *uint64, + receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, ) (err error) { nonce := state.GetNonce(msg.From()) expectedTx := types.NewTransaction(nonce, *msg.To(), msg.Value(), msg.Gas(), msg.GasPrice(), msg.Data()) expectedHash := p.signer.Hash(expectedTx) - if msg.From() == p.val { + if msg.From() == p.val && mining { expectedTx, err = p.signTxFn(accounts.Account{Address: msg.From()}, expectedTx, p.chainConfig.ChainID) if err != nil { return err From 2ff7a21d64b41efeb8c75667828872cf1b4f34f7 Mon Sep 17 00:00:00 2001 From: fudongbai <296179868@qq.com> Date: Mon, 15 Jun 2020 17:11:06 +0800 Subject: [PATCH 04/12] update stale depth --- eth/fetcher/block_fetcher.go | 2 +- miner/worker.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go index 7690a53862..d6951d2f17 100644 --- a/eth/fetcher/block_fetcher.go +++ b/eth/fetcher/block_fetcher.go @@ -37,7 +37,7 @@ const ( ) const ( - maxUncleDist = 7 // Maximum allowed backward distance from the chain head + maxUncleDist = 11 // Maximum allowed backward distance from the chain head maxQueueDist = 32 // Maximum allowed distance from the chain head to queue hashLimit = 256 // Maximum number of unique blocks a peer may have announced blockLimit = 64 // Maximum number of unique blocks a peer may have delivered diff --git a/miner/worker.go b/miner/worker.go index fd7ac76e93..79272fe870 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -56,7 +56,7 @@ const ( resubmitAdjustChanSize = 10 // miningLogAtDepth is the number of confirmations before logging successful mining. - miningLogAtDepth = 15 + miningLogAtDepth = 11 // minRecommitInterval is the minimal time interval to recreate the mining block with // any newly arrived transactions. @@ -75,7 +75,7 @@ const ( intervalAdjustBias = 200 * 1000.0 * 1000.0 // staleThreshold is the maximum depth of the acceptable stale block. - staleThreshold = 7 + staleThreshold = 11 ) var ( @@ -356,7 +356,7 @@ func (w *worker) newWorkLoop(recommit time.Duration) { commit(false, commitInterruptNewHead) case head := <-w.chainHeadCh: - if !w.isRunning(){ + if !w.isRunning() { continue } clearPending(head.Block.NumberU64()) From 4bd4469151d3bdf4ef5601036f329f660148ef86 Mon Sep 17 00:00:00 2001 From: fudongbai <296179868@qq.com> Date: Thu, 18 Jun 2020 00:26:27 +0800 Subject: [PATCH 05/12] add gas limit check in parlia implement --- consensus/parlia/parlia.go | 9 ++++++++- miner/worker.go | 1 + params/protocol_params.go | 25 +++++++++++++------------ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 323daf2973..4338f83e15 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -336,7 +336,10 @@ func (p *Parlia) verifyHeader(chain consensus.ChainReader, header *types.Header, if len(header.Extra) < extraVanity+extraSeal { return errMissingSignature } - + // Verify that the gasUsed is <= gasLimit + if header.GasUsed > header.GasLimit { + return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) + } // check extra data isEpoch := number%p.config.Epoch == 0 @@ -742,6 +745,10 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainReader, header *types. if err != nil { panic(err) } + // should not happen. Once happen, stop the node is better than broadcast the block + if header.GasLimit < header.GasUsed { + panic("Gas consumption of system txs exceed the gas limit") + } header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) diff --git a/miner/worker.go b/miner/worker.go index 79272fe870..f0c622d181 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -732,6 +732,7 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin if w.current.gasPool == nil { w.current.gasPool = new(core.GasPool).AddGas(w.current.header.GasLimit) + w.current.gasPool.SubGas(params.SystemTxsGas) } var coalescedLogs []*types.Log diff --git a/params/protocol_params.go b/params/protocol_params.go index ab5411d2e0..d759305cac 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -19,21 +19,22 @@ package params import "math/big" const ( - GasLimitBoundDivisor uint64 = 256 // The bound divisor of the gas limit, used in update calculations. + GasLimitBoundDivisor uint64 = 256 // The bound divisor of the gas limit, used in update calculations. MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be. GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. - MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. - ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction. - SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added. - CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero. - CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior. - TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions. - TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions. - TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions. - QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation. - LogDataGas uint64 = 8 // Per byte in a LOG* operation's data. - CallStipend uint64 = 2300 // Free gas given at beginning of call. + MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. + ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction. + SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added. + CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero. + CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior. + TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions. + SystemTxsGas uint64 = 100000 // The gas reserved for system txs; only for parlia consensus + TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions. + TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions. + QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation. + LogDataGas uint64 = 8 // Per byte in a LOG* operation's data. + CallStipend uint64 = 2300 // Free gas given at beginning of call. Sha3Gas uint64 = 30 // Once per SHA3 operation. Sha3WordGas uint64 = 6 // Once per word of the SHA3 operation's data. From 6a19c9803c81ca6c0fce83ec3d4faa6f5cf52665 Mon Sep 17 00:00:00 2001 From: fudongbai <296179868@qq.com> Date: Wed, 24 Jun 2020 16:17:22 +0800 Subject: [PATCH 06/12] remove redundant gaslimit check --- consensus/parlia/parlia.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 4338f83e15..304b6f123b 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -336,10 +336,6 @@ func (p *Parlia) verifyHeader(chain consensus.ChainReader, header *types.Header, if len(header.Extra) < extraVanity+extraSeal { return errMissingSignature } - // Verify that the gasUsed is <= gasLimit - if header.GasUsed > header.GasLimit { - return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) - } // check extra data isEpoch := number%p.config.Epoch == 0 From 5e4f5785c72f9478787e12e6b1f9b4dbfc8a9f69 Mon Sep 17 00:00:00 2001 From: zjubfd <296179868@qq.com> Date: Tue, 30 Jun 2020 16:15:12 +0800 Subject: [PATCH 07/12] fix debug_traceTransaction crashed issue (#13) --- core/vm/interpreter.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 5d213acc83..949a39dacf 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -162,10 +162,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // as every returning call will return new data anyway. in.returnData = nil + // TODO temporary fix for issue // Don't bother with the execution if there's no code. - if len(contract.Code) == 0 { - return nil, nil - } + //if len(contract.Code) == 0 { + // return nil, nil + //} var ( op OpCode // current opcode From 511bbf546fb73a6e88a5cd1975784320180e6281 Mon Sep 17 00:00:00 2001 From: zjubfd <296179868@qq.com> Date: Tue, 30 Jun 2020 16:16:26 +0800 Subject: [PATCH 08/12] add bep2p tokens for faucet (#5) --- cmd/faucet/faucet.go | 117 +++++++++++++++++++++++++++++++++-------- cmd/faucet/faucet.html | 11 +++- cmd/faucet/website.go | 8 +-- 3 files changed, 108 insertions(+), 28 deletions(-) diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go index 3427a7af7a..70bc540c1c 100644 --- a/cmd/faucet/faucet.go +++ b/cmd/faucet/faucet.go @@ -41,6 +41,8 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" @@ -83,11 +85,15 @@ var ( noauthFlag = flag.Bool("noauth", false, "Enables funding requests without authentication") logFlag = flag.Int("loglevel", 3, "Log level to use for Ethereum and the faucet") - fixGasPrice = flag.Int64("faucet.fixedprice", 0, "Will use fixed gas price if specified") + bep2eContracts = flag.String("bep2eContracts", "", "the list of bep2p contracts") + bep2eSymbols = flag.String("bep2eSymbols", "", "the symbol of bep2p tokens") + bep2eAmounts = flag.String("bep2eAmounts", "", "the amount of bep2p tokens") + fixGasPrice = flag.Int64("faucet.fixedprice", 0, "Will use fixed gas price if specified") ) var ( - ether = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) + ether = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) + bep2eAbiJson = `[ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "inputs": [], "name": "totalSupply", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "decimals", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "symbol", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getOwner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "account", "type": "address" } ], "name": "balanceOf", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transfer", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "_owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "approve", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "sender", "type": "address" }, { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" } ]` ) var ( @@ -110,7 +116,39 @@ func main() { amounts[i] = strings.TrimSuffix(amounts[i], "s") } } + bep2eNumAmounts := make([]string, 0) + if bep2eAmounts != nil && len(*bep2eAmounts) > 0 { + bep2eNumAmounts = strings.Split(*bep2eAmounts, ",") + } + + symbols := make([]string, 0) + if bep2eSymbols != nil && len(*bep2eSymbols) > 0 { + symbols = strings.Split(*bep2eSymbols, ",") + } + contracts := make([]string, 0) + if bep2eContracts != nil && len(*bep2eContracts) > 0 { + contracts = strings.Split(*bep2eContracts, ",") + } + + if len(bep2eNumAmounts) != len(symbols) || len(symbols) != len(contracts) { + log.Crit("Length of bep2eContracts, bep2eSymbols, bep2eAmounts mismatch") + } + + bep2eInfos := make(map[string]bep2eInfo, 0) + for idx, s := range symbols { + n, ok := big.NewInt(0).SetString(bep2eNumAmounts[idx], 10) + if !ok { + log.Crit("failed to parse bep2eAmounts") + } + amountStr := big.NewFloat(0).Quo(big.NewFloat(0).SetInt(n), big.NewFloat(0).SetInt64(params.Ether)).String() + + bep2eInfos[s] = bep2eInfo{ + Contract: common.HexToAddress(contracts[idx]), + Amount: *n, + AmountStr: amountStr, + } + } // Load up and render the faucet website tmpl, err := Asset("faucet.html") if err != nil { @@ -118,10 +156,11 @@ func main() { } website := new(bytes.Buffer) err = template.Must(template.New("").Parse(string(tmpl))).Execute(website, map[string]interface{}{ - "Network": *netnameFlag, - "Amounts": amounts, - "Recaptcha": *captchaToken, - "NoAuth": *noauthFlag, + "Network": *netnameFlag, + "Amounts": amounts, + "Recaptcha": *captchaToken, + "NoAuth": *noauthFlag, + "Bep2eInfos": bep2eInfos, }) if err != nil { log.Crit("Failed to render the faucet template", "err", err) @@ -162,7 +201,7 @@ func main() { ks.Unlock(acc, pass) // Assemble and start the faucet light service - faucet, err := newFaucet(genesis, *ethPortFlag, enodes, *netFlag, *statsFlag, ks, website.Bytes()) + faucet, err := newFaucet(genesis, *ethPortFlag, enodes, *netFlag, *statsFlag, ks, website.Bytes(), bep2eInfos) if err != nil { log.Crit("Failed to start faucet", "err", err) } @@ -181,6 +220,12 @@ type request struct { Tx *types.Transaction `json:"tx"` // Transaction funding the account } +type bep2eInfo struct { + Contract common.Address + Amount big.Int + AmountStr string +} + // faucet represents a crypto faucet backed by an Ethereum light client. type faucet struct { config *params.ChainConfig // Chain configurations for signing @@ -201,9 +246,12 @@ type faucet struct { update chan struct{} // Channel to signal request updates lock sync.RWMutex // Lock protecting the faucet's internals + + bep2eInfos map[string]bep2eInfo + bep2eAbi abi.ABI } -func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) { +func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte, bep2eInfos map[string]bep2eInfo) (*faucet, error) { // Assemble the raw devp2p protocol stack stack, err := node.New(&node.Config{ Name: "geth", @@ -222,6 +270,10 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u if err != nil { return nil, err } + bep2eAbi, err := abi.JSON(strings.NewReader(bep2eAbiJson)) + if err != nil { + return nil, err + } // Assemble the Ethereum light client protocol if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { cfg := eth.DefaultConfig @@ -261,14 +313,16 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u client := ethclient.NewClient(api) return &faucet{ - config: genesis.Config, - stack: stack, - client: client, - index: index, - keystore: ks, - account: ks.Accounts()[0], - timeouts: make(map[string]time.Time), - update: make(chan struct{}, 1), + config: genesis.Config, + stack: stack, + client: client, + index: index, + keystore: ks, + account: ks.Accounts()[0], + timeouts: make(map[string]time.Time), + update: make(chan struct{}, 1), + bep2eInfos: bep2eInfos, + bep2eAbi: bep2eAbi, }, nil } @@ -371,6 +425,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) { URL string `json:"url"` Tier uint `json:"tier"` Captcha string `json:"captcha"` + Symbol string `json:"symbol"` } if err = conn.ReadJSON(&msg); err != nil { return @@ -475,13 +530,31 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) { fund bool timeout time.Time ) - if timeout = f.timeouts[username]; time.Now().After(timeout) { - // User wasn't funded recently, create the funding transaction - amount := new(big.Int).Mul(big.NewInt(int64(*payoutFlag)), ether) - amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil)) - amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil)) - tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil) + if timeout = f.timeouts[username]; time.Now().After(timeout) { + var tx *types.Transaction + if msg.Symbol == "BNB" { + // User wasn't funded recently, create the funding transaction + amount := new(big.Int).Mul(big.NewInt(int64(*payoutFlag)), ether) + amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil)) + amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil)) + + tx = types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil) + } else { + tokenInfo, ok := f.bep2eInfos[msg.Symbol] + if !ok { + f.lock.Unlock() + log.Warn("Failed to find symbol", "symbol", msg.Symbol) + continue + } + input, err := f.bep2eAbi.Pack("transfer", address, &tokenInfo.Amount) + if err != nil { + f.lock.Unlock() + log.Warn("Failed to pack transfer transaction", "err", err) + continue + } + tx = types.NewTransaction(f.nonce+uint64(len(f.reqs)), tokenInfo.Contract, nil, 420000, f.price, input) + } signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainID) if err != nil { f.lock.Unlock() diff --git a/cmd/faucet/faucet.html b/cmd/faucet/faucet.html index d14c98fca5..36748ae9e1 100644 --- a/cmd/faucet/faucet.html +++ b/cmd/faucet/faucet.html @@ -53,7 +53,13 @@