From bf626ddc958ce9c50a2aa420775ec12e8fa2146f Mon Sep 17 00:00:00 2001 From: AnilChinchawale Date: Sat, 16 Mar 2019 16:00:19 +0530 Subject: [PATCH] Core Updated --- core/block_validator_test.go | 3 --- core/blockchain.go | 26 ++++++++++++--------- core/state/statedb.go | 8 +++++++ core/state_processor.go | 44 ++++++++++++++++++++++++++++++++++++ core/state_transition.go | 11 +++++++-- core/tx_pool.go | 24 ++++++++++++++++---- 6 files changed, 95 insertions(+), 21 deletions(-) diff --git a/core/block_validator_test.go b/core/block_validator_test.go index e334b3c3cd..c44def0148 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -48,7 +48,6 @@ func TestHeaderVerification(t *testing.T) { for i := 0; i < len(blocks); i++ { for j, valid := range []bool{true, false} { var results <-chan error - if valid { engine := ethash.NewFaker() _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}) @@ -104,7 +103,6 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) { // also an invalid chain (enough if one arbitrary block is invalid). for i, valid := range []bool{true, false} { var results <-chan error - if valid { chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}) _, results = chain.engine.VerifyHeaders(chain, headers, seals) @@ -175,7 +173,6 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) { // Start the verifications and immediately abort chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}) defer chain.Stop() - abort, results := chain.engine.VerifyHeaders(chain, headers, seals) close(abort) diff --git a/core/blockchain.go b/core/blockchain.go index 9b6be16ccc..025595ca13 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -141,10 +141,9 @@ type BlockChain struct { validator Validator // block and state validator interface vmConfig vm.Config - badBlocks *lru.Cache // Bad block cache - IPCEndpoint string - Client *ethclient.Client // Global ipc client instance. - HookWriteRewards func(header *types.Header) + badBlocks *lru.Cache // Bad block cache + IPCEndpoint string + Client *ethclient.Client // Global ipc client instance. } // NewBlockChain returns a fully initialised block chain using information @@ -507,6 +506,12 @@ func (bc *BlockChain) insert(block *types.Block) { } bc.currentBlock.Store(block) + // save cache BlockSigners + if bc.chainConfig.XDPoS != nil && !bc.chainConfig.IsTIPSigning(block.Number()) { + engine := bc.Engine().(*XDPoS.XDPoS) + engine.CacheData(block.Header(), block.Transactions(), bc.GetReceiptsByHash(block.Hash())) + } + // If the block is better than our head or is on a different chain, force update heads if updateHeads { bc.hc.SetCurrentHeader(block.Header()) @@ -1014,6 +1019,11 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. if status == CanonStatTy { bc.insert(block) } + // save cache BlockSigners + if bc.chainConfig.XDPoS != nil && bc.chainConfig.IsTIPSigning(block.Number()) { + engine := bc.Engine().(*XDPoS.XDPoS) + engine.CacheSigner(block.Header().Hash(), block.Transactions()) + } bc.futureBlocks.Remove(block.Hash()) return status, nil } @@ -1067,7 +1077,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty for i, block := range chain { headers[i] = block.Header() - seals[i] = true + seals[i] = false bc.downloadingBlock.Add(block.Hash(), true) } abort, results := bc.engine.VerifyHeaders(bc, headers, seals) @@ -1222,9 +1232,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty } } } - if bc.HookWriteRewards != nil { - bc.HookWriteRewards(block.Header()) - } } // Append a single chain head event if we've progressed the chain if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() { @@ -1431,9 +1438,6 @@ func (bc *BlockChain) insertBlock(block *types.Block) ([]interface{}, []*types.L events = append(events, ChainHeadEvent{block}) log.Debug("New ChainHeadEvent from fetcher ", "number", block.NumberU64(), "hash", block.Hash()) } - if bc.HookWriteRewards != nil { - bc.HookWriteRewards(block.Header()) - } return events, coalescedLogs, nil } diff --git a/core/state/statedb.go b/core/state/statedb.go index bd67e789d5..2ae700cd67 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -357,6 +357,14 @@ func (self *StateDB) deleteStateObject(stateObject *stateObject) { self.setError(self.trie.TryDelete(addr[:])) } +// DeleteAddress removes the address from the state trie. +func (self *StateDB) DeleteAddress(addr common.Address) { + stateObject := self.getStateObject(addr) + if stateObject != nil && !stateObject.deleted { + self.deleteStateObject(stateObject) + } +} + // Retrieve a state object given my the address. Returns nil if not found. func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { // Prefer 'live' objects. diff --git a/core/state_processor.go b/core/state_processor.go index 6ec3fcc6f1..c2df09f994 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -73,6 +73,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } + if common.TIPSigning.Cmp(header.Number) == 0 { + statedb.DeleteAddress(common.HexToAddress(common.BlockSigners)) + } InitSignerInTransactions(p.config, header, block.Transactions()) for i, tx := range block.Transactions() { statedb.Prepare(tx.Hash(), block.Hash(), i) @@ -101,6 +104,9 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } + if common.TIPSigning.Cmp(header.Number) == 0 { + statedb.DeleteAddress(common.HexToAddress(common.BlockSigners)) + } if cBlock.stop { return nil, nil, 0, ErrStopPreparingBlock } @@ -132,6 +138,9 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) { + if tx.To() != nil && tx.To().String() == common.BlockSigners && config.IsTIPSigning(header.Number) { + return ApplySignTransaction(config, statedb, header, tx, usedGas) + } msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) if err != nil { return nil, 0, err @@ -171,6 +180,41 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common return receipt, gas, err } +func ApplySignTransaction(config *params.ChainConfig, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, uint64, error) { + // Update the state with pending changes + var root []byte + if config.IsByzantium(header.Number) { + statedb.Finalise(true) + } else { + root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() + } + from, err := types.Sender(types.MakeSigner(config, header.Number), tx) + if err != nil { + return nil, 0, err + } + nonce := statedb.GetNonce(from) + if nonce < tx.Nonce() { + return nil, 0, ErrNonceTooHigh + } else if nonce > tx.Nonce() { + return nil, 0, ErrNonceTooLow + } + statedb.SetNonce(from, nonce+1) + // Create a new receipt for the transaction, storing the intermediate root and gas used by the tx + // based on the eip phase, we're passing wether the root touch-delete accounts. + receipt := types.NewReceipt(root, false, *usedGas) + receipt.TxHash = tx.Hash() + receipt.GasUsed = 0 + // if the transaction created a contract, store the creation address in the receipt. + // Set the receipt logs and create a bloom for filtering + log := &types.Log{} + log.Address = common.HexToAddress(common.BlockSigners) + log.BlockNumber = header.Number.Uint64() + statedb.AddLog(log) + receipt.Logs = statedb.GetLogs(tx.Hash()) + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + return receipt, 0, nil +} + func InitSignerInTransactions(config *params.ChainConfig, header *types.Header, txs types.Transactions) { nWorker := runtime.NumCPU() signer := types.MakeSigner(config, header.Number) diff --git a/core/state_transition.go b/core/state_transition.go index b19bc12e42..23ab89190d 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -229,15 +229,22 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo // error. vmerr error ) + // for debugging purpose + // TODO: clean it after fixing the issue https://github.com/XDCchain/XDCchain/issues/401 + var contractAction string + nonce := uint64(1) if contractCreation { ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value) + contractAction = "contract creation" } else { // Increment the nonce for the next transaction - st.state.SetNonce(sender.Address(), st.state.GetNonce(sender.Address())+1) + nonce = st.state.GetNonce(sender.Address()) + 1 + st.state.SetNonce(sender.Address(), nonce) ret, st.gas, vmerr = evm.Call(sender, st.to().Address(), st.data, st.gas, st.value) + contractAction = "contract call" } if vmerr != nil { - log.Debug("VM returned with error", "err", vmerr) + log.Debug("VM returned with error", "action", contractAction, "contract address", st.to().Address(), "gas", st.gas, "gasPrice", st.gasPrice, "nonce", nonce, "err", vmerr) // The only possible consensus-error would be if there wasn't // sufficient balance to make the transfer happen. The first // balance transfer may never fail. diff --git a/core/tx_pool.go b/core/tx_pool.go index 63dbf3ac9e..3d7be4c11d 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -81,7 +81,11 @@ var ( ErrZeroGasPrice = errors.New("zero gas price") + ErrUnderMinGasPrice = errors.New("under min gas price") + ErrDuplicateSpecialTransaction = errors.New("duplicate a special transaction") + + ErrMinDeploySMC = errors.New("smart contract creation cost is under allowance") ) var ( @@ -214,8 +218,8 @@ type TxPool struct { wg sync.WaitGroup // for shutdown sync - homestead bool - IsMasterNode func(address common.Address) bool + homestead bool + IsSigner func(address common.Address) bool } // NewTxPool creates a new transaction pool to gather, sort and filter inbound @@ -587,8 +591,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { } // Drop non-local transactions under our own minimal accepted gas price local = local || pool.locals.contains(from) // account may be local even if the transaction arrived from the network - if !local && tx.To() != nil && pool.gasPrice.Cmp(tx.GasPrice()) > 0 { - if !tx.IsSpecialTransaction() || (pool.IsMasterNode != nil && !pool.IsMasterNode(from)) { + if !local && pool.gasPrice.Cmp(tx.GasPrice()) > 0 { + if !tx.IsSpecialTransaction() || (pool.IsSigner != nil && !pool.IsSigner(from)) { return ErrUnderpriced } } @@ -619,6 +623,16 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if tx.GasPrice().Cmp(new(big.Int).SetInt64(0)) == 0 { return ErrZeroGasPrice } + + // under min gas price + if tx.GasPrice().Cmp(new(big.Int).SetInt64(common.MinGasPrice)) < 0 { + return ErrUnderMinGasPrice + } + } + + minGasDeploySMC := new(big.Int).Mul(new(big.Int).SetUint64(10), new(big.Int).SetUint64(params.Ether)) + if tx.To() == nil && (tx.Cost().Cmp(minGasDeploySMC) < 0 || tx.GasPrice().Cmp(new(big.Int).SetUint64(10000*params.Shannon)) < 0) { + return ErrMinDeploySMC } return nil @@ -647,7 +661,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { return false, err } from, _ := types.Sender(pool.signer, tx) // already validated - if tx.IsSpecialTransaction() && pool.IsMasterNode != nil && pool.IsMasterNode(from) && pool.pendingState.GetNonce(from) == tx.Nonce() { + if tx.IsSpecialTransaction() && pool.IsSigner != nil && pool.IsSigner(from) && pool.pendingState.GetNonce(from) == tx.Nonce() { return pool.promoteSpecialTx(from, tx) } // If the transaction pool is full, discard underpriced transactions