From 78d17e64cdf479d175722d96ca30fe9d679e23bf Mon Sep 17 00:00:00 2001 From: denis k Date: Fri, 24 Aug 2018 15:40:42 +1000 Subject: [PATCH] merge --- consensus/lcp/epoch_context_test.go | 61 +++++++++++++++++++++++++++-- consensus/lcp/lcp.go | 2 +- core/state_processor.go | 43 +++++++++++++++++--- core/types/transaction.go | 5 +++ 4 files changed, 102 insertions(+), 9 deletions(-) diff --git a/consensus/lcp/epoch_context_test.go b/consensus/lcp/epoch_context_test.go index 97cf77db26..f11364a8fe 100644 --- a/consensus/lcp/epoch_context_test.go +++ b/consensus/lcp/epoch_context_test.go @@ -1,6 +1,8 @@ package lcp import ( + "errors" + "fmt" "math/big" "testing" @@ -14,6 +16,44 @@ import ( //types2 "github.com/pavelkrolevets/go-ethereum/core/types" ) +func (ec *EpochContext) cVotes() (votes map[common.Address]*big.Int, err error) { + votes = map[common.Address]*big.Int{} + delegateTrie := ec.Context.DelegateTrie() + candidateTrie := ec.Context.CandidateTrie() + statedb := ec.statedb + + iterCandidate := trie.NewIterator(candidateTrie.NodeIterator(nil)) + existCandidate := iterCandidate.Next() + if !existCandidate { + return votes, errors.New("no candidates") + } + for existCandidate { + candidate := iterCandidate.Value + candidateAddr := common.BytesToAddress(candidate) + delegateIterator := trie.NewIterator(delegateTrie.PrefixIterator(candidate)) + existDelegator := delegateIterator.Next() + if !existDelegator { + votes[candidateAddr] = new(big.Int) + existCandidate = iterCandidate.Next() + continue + } + for existDelegator { + delegator := delegateIterator.Value + score, ok := votes[candidateAddr] + if !ok { + score = new(big.Int) + } + delegatorAddr := common.BytesToAddress(delegator) + weight := statedb.GetBalance(delegatorAddr) + score.Add(score, weight) + votes[candidateAddr] = score + existDelegator = delegateIterator.Next() + } + existCandidate = iterCandidate.Next() + } + return votes, nil +} + func TestEpochContextCountVotes(t *testing.T) { voteMap := map[common.Address][]common.Address{ common.HexToAddress("0x44d1ce0b7cb3588bca96151fe1bc05af38f91b6e"): { @@ -38,10 +78,12 @@ func TestEpochContextCountVotes(t *testing.T) { assert.Nil(t, err) epochContext := &EpochContext{ - Context: LCPContext, - statedb: stateDB, + Context: LCPContext, + statedb: stateDB, } - _, err = epochContext.countVotes() + + // _, err = epochContext.countVotes() + _, err = epochContext.cVotes() assert.NotNil(t, err) for candidate, electors := range voteMap { @@ -49,17 +91,30 @@ func TestEpochContextCountVotes(t *testing.T) { for _, elector := range electors { stateDB.SetBalance(elector, big.NewInt(balance)) assert.Nil(t, LCPContext.Delegate(elector, candidate)) + + // print candidates list + _, e := epochContext.Context.VoteTrie().TryGet([]byte(elector.Bytes())) + if _, ok := e.(*trie.MissingNodeError); !ok { + fmt.Println(err) + } } } + result, err := epochContext.countVotes() assert.Nil(t, err) assert.Equal(t, len(voteMap), len(result)) + for candidate, electors := range voteMap { voteCount, ok := result[candidate] assert.True(t, ok) + + fmt.Println("voteCount =", voteCount) + fmt.Println("ele =", balance*int64(len(electors))) + assert.Equal(t, balance*int64(len(electors)), voteCount.Int64()) } } + // //func TestLookupValidator(t *testing.T) { // db, _ := ethdb.NewMemDatabase() diff --git a/consensus/lcp/lcp.go b/consensus/lcp/lcp.go index 9f0bc697f3..72604a8d8a 100644 --- a/consensus/lcp/lcp.go +++ b/consensus/lcp/lcp.go @@ -356,7 +356,7 @@ func AccumulateRewards(config *params.ChainConfig, state *state.StateDB, header } func (d *LCP) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, receipts []*types.Receipt, LCPContext *types.LCPContext) (*types.Block, error) { + uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { // Accumulate block rewards and commit the final state root AccumulateRewards(chain.Config(), state, header, uncles) header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) diff --git a/core/state_processor.go b/core/state_processor.go index e5e3d88c42..1acf69a24b 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -17,6 +17,8 @@ package core import ( + "math/big" + "github.com/pavelkrolevets/go-ethereum/common" "github.com/pavelkrolevets/go-ethereum/consensus" "github.com/pavelkrolevets/go-ethereum/consensus/misc" @@ -65,10 +67,11 @@ 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) } + // Set out block dpos context // Iterate over and process the individual transactions for i, tx := range block.Transactions() { statedb.Prepare(tx.Hash(), block.Hash(), i) - receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg) + receipt, _, err := ApplyTransaction(p.config, block.LCPCtx(), p.bc, nil, gp, statedb, header, tx, usedGas, cfg) if err != nil { return nil, nil, 0, err } @@ -85,11 +88,15 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) { +func ApplyTransaction(config *params.ChainConfig, lcpContext *types.LCPContext, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) { msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) if err != nil { return nil, 0, err } + if msg.To() == nil && msg.Type() != types.Binary { + return nil, 0, types.ErrInvalidType + } + // Create a new context to be used in the EVM environment context := NewEVMContext(msg, header, bc, author) // Create a new environment which holds all relevant information @@ -100,6 +107,12 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo if err != nil { return nil, 0, err } + if msg.Type() != types.Binary { + if err = applyLcpMessage(lcpContext, msg); err != nil { + return nil, 0, err + } + } + // Update the state with pending changes var root []byte if config.IsByzantium(header.Number) { @@ -107,20 +120,40 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo } else { root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() } - *usedGas += gas + // *usedGas += gas + usedGas.Add(usedGas, gas) // 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, failed, *usedGas) + // receipt := types.NewReceipt(root, failed, *usedGas) + receipt := types.NewReceipt(root, failed, usedGas) receipt.TxHash = tx.Hash() - receipt.GasUsed = gas + // receipt.GasUsed = gas + receipt.GasUsed = new(big.Int).Set(gas) // if the transaction created a contract, store the creation address in the receipt. if msg.To() == nil { receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce()) } + // Set the receipt logs and create a bloom for filtering receipt.Logs = statedb.GetLogs(tx.Hash()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) return receipt, gas, err } + +func applyLcpMessage(lcpContext *types.LCPContext, msg types.Message) error { + switch msg.Type() { + case types.LoginCandidate: + lcpContext.BecomeCandidate(msg.From()) + case types.LogoutCandidate: + lcpContext.KickoutCandidate(msg.From()) + case types.Delegate: + lcpContext.Delegate(msg.From(), *(msg.To())) + case types.UnDelegate: + lcpContext.UnDelegate(msg.From(), *(msg.To())) + default: + return types.ErrInvalidType + } + return nil +} diff --git a/core/types/transaction.go b/core/types/transaction.go index 4673198c6f..6ff491dc7a 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -31,6 +31,9 @@ import ( //go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go +// transaction type +type TxType uint8 + var ( ErrInvalidSig = errors.New("invalid transaction v, r, s values") ) @@ -387,6 +390,7 @@ type Message struct { gasPrice *big.Int data []byte checkNonce bool + txType TxType } func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool) Message { @@ -410,3 +414,4 @@ func (m Message) Gas() uint64 { return m.gasLimit } func (m Message) Nonce() uint64 { return m.nonce } func (m Message) Data() []byte { return m.data } func (m Message) CheckNonce() bool { return m.checkNonce } +func (m Message) Type() TxType { return m.txType }