From 312cc4a59fb228319c26b4b2eb8bed64724afbf3 Mon Sep 17 00:00:00 2001 From: Tuna Date: Tue, 1 Jan 2019 17:01:03 +0700 Subject: [PATCH 01/21] add BlockSigners reader --- contracts/smcReader.go | 96 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 contracts/smcReader.go diff --git a/contracts/smcReader.go b/contracts/smcReader.go new file mode 100644 index 0000000000..43558891e6 --- /dev/null +++ b/contracts/smcReader.go @@ -0,0 +1,96 @@ +package contracts + +import ( + "fmt" + "strings" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/contracts/blocksigner/contract" + "github.com/ethereum/go-ethereum/core/types" +) + +var ( + slotBlockSignerMapping = map[string]uint64{ + "getSigners": 0, + } + ParsedBlockSignerABI, _ = abi.JSON(strings.NewReader(contract.BlockSignerABI)) +) + +/////////////////////////////////////// +////// BlockSigner SMC /////////// +/////////////////////////////////////// +func GetSigners(statedb *state.StateDB, parsed abi.ABI, block *types.Block) ([]common.Address) { + methodName := "getSigners" + fmt.Printf("---%s---\n", methodName) + start := time.Now() + signers := getSigners(parsed, statedb, common.HexToAddress(common.BlockSigners), methodName, block.Hash()) + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) + return signers +} + +func getSigners(parsed abi.ABI, statedb *state.StateDB, address common.Address, methodName string, input ...common.Hash) ([]common.Address) { + keys := getKeyStorage(statedb, address, parsed, methodName, input...) + rets := []common.Address{} + ret := common.Address{} + for _, key := range keys { + value := statedb.GetState(address, key) + method := parsed.Methods[methodName] + switch method.Outputs[0].Type.T { + case abi.StringTy: + //do nothing - output can't be string in this method + //ret = string(value.Bytes()) + default: + parsed.Unpack(&ret, methodName, value.Bytes()) + rets = append(rets, ret) + } + } + return rets +} + +func getKeyStorage(statedb *state.StateDB, address common.Address, parsed abi.ABI, methodName string, input ...common.Hash) ([]common.Hash) { + method, ok := parsed.Methods[methodName] + slot := slotBlockSignerMapping[methodName] + keys := []common.Hash{} + + // do not support function call + if ok && len(method.Inputs) <= 1 || len(method.Outputs) == 1 { + if len(method.Inputs) == 0 { + keys = append(keys, getKey(slot)) + } else { + // support first input + keyArrSlot := mapLocAtKey(input[0], slot) + arrSlot := statedb.GetState(address, keyArrSlot) + arrLength := arrSlot.Big().Uint64() + for i := uint64(0); i < arrLength; i++ { + valueHash := arrDynamicLocAtElement(keyArrSlot, i, 1) + keys = append(keys, valueHash) + } + } + } + return keys +} + +func getKey(slot uint64) common.Hash { + updatedKey := common.BigToHash(new(big.Int).SetUint64(slot)) + return updatedKey +} + +func mapLocAtKey(key common.Hash, slot uint64) common.Hash { + slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) + updatedKey := crypto.Keccak256Hash(key.Bytes(), slotHash.Bytes()) + return updatedKey +} + +func arrDynamicLocAtElement(slotHash common.Hash, index uint64, elementSize uint64) common.Hash { + slotKecBig := crypto.Keccak256Hash(slotHash.Bytes()).Big() + //arrBig = slotKecBig + index * elementSize + arrBig := slotKecBig.Add(slotKecBig, new(big.Int).SetUint64(index * elementSize)) + arrHash := common.BigToHash(arrBig) + return arrHash +} From f3ee5910bb812226c66e7901eb16ea22bd0c6cb6 Mon Sep 17 00:00:00 2001 From: Tuna Date: Wed, 2 Jan 2019 13:58:58 +0700 Subject: [PATCH 02/21] add smc ultilities --- contracts/smcReader.go | 44 +++++++++++++----------------------------- contracts/smcUtils.go | 30 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 31 deletions(-) create mode 100644 contracts/smcUtils.go diff --git a/contracts/smcReader.go b/contracts/smcReader.go index 43558891e6..3392e1d6ea 100644 --- a/contracts/smcReader.go +++ b/contracts/smcReader.go @@ -3,13 +3,11 @@ package contracts import ( "fmt" "strings" - "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/contracts/blocksigner/contract" "github.com/ethereum/go-ethereum/core/types" ) @@ -35,25 +33,28 @@ func GetSigners(statedb *state.StateDB, parsed abi.ABI, block *types.Block) ([]c } func getSigners(parsed abi.ABI, statedb *state.StateDB, address common.Address, methodName string, input ...common.Hash) ([]common.Address) { - keys := getKeyStorage(statedb, address, parsed, methodName, input...) + keys := getKeys(statedb, address, parsed, methodName, input...) rets := []common.Address{} ret := common.Address{} for _, key := range keys { value := statedb.GetState(address, key) method := parsed.Methods[methodName] switch method.Outputs[0].Type.T { - case abi.StringTy: - //do nothing - output can't be string in this method - //ret = string(value.Bytes()) + case abi.AddressTy: + ret = common.BytesToAddress(value.Bytes()) default: - parsed.Unpack(&ret, methodName, value.Bytes()) - rets = append(rets, ret) + err := parsed.Unpack(&ret, methodName, value.Bytes()) + if err != nil { + fmt.Printf("err: %v\n", err) + } + //ret = common.BytesToAddress(value.Bytes()) } + rets = append(rets, ret) } return rets } -func getKeyStorage(statedb *state.StateDB, address common.Address, parsed abi.ABI, methodName string, input ...common.Hash) ([]common.Hash) { +func getKeys(statedb *state.StateDB, address common.Address, parsed abi.ABI, methodName string, input ...common.Hash) ([]common.Hash) { method, ok := parsed.Methods[methodName] slot := slotBlockSignerMapping[methodName] keys := []common.Hash{} @@ -61,36 +62,17 @@ func getKeyStorage(statedb *state.StateDB, address common.Address, parsed abi.AB // do not support function call if ok && len(method.Inputs) <= 1 || len(method.Outputs) == 1 { if len(method.Inputs) == 0 { - keys = append(keys, getKey(slot)) + keys = append(keys, getLocSimpleVariable(slot)) } else { // support first input - keyArrSlot := mapLocAtKey(input[0], slot) + keyArrSlot := getLocMappingAtKey(input[0], slot) arrSlot := statedb.GetState(address, keyArrSlot) arrLength := arrSlot.Big().Uint64() for i := uint64(0); i < arrLength; i++ { - valueHash := arrDynamicLocAtElement(keyArrSlot, i, 1) + valueHash := getLocDynamicArrAtElement(keyArrSlot, i, 1) keys = append(keys, valueHash) } } } return keys } - -func getKey(slot uint64) common.Hash { - updatedKey := common.BigToHash(new(big.Int).SetUint64(slot)) - return updatedKey -} - -func mapLocAtKey(key common.Hash, slot uint64) common.Hash { - slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) - updatedKey := crypto.Keccak256Hash(key.Bytes(), slotHash.Bytes()) - return updatedKey -} - -func arrDynamicLocAtElement(slotHash common.Hash, index uint64, elementSize uint64) common.Hash { - slotKecBig := crypto.Keccak256Hash(slotHash.Bytes()).Big() - //arrBig = slotKecBig + index * elementSize - arrBig := slotKecBig.Add(slotKecBig, new(big.Int).SetUint64(index * elementSize)) - arrHash := common.BigToHash(arrBig) - return arrHash -} diff --git a/contracts/smcUtils.go b/contracts/smcUtils.go new file mode 100644 index 0000000000..da53c8d2e5 --- /dev/null +++ b/contracts/smcUtils.go @@ -0,0 +1,30 @@ +package contracts + +import ( + "math/big" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +func getLocSimpleVariable (slot uint64) common.Hash { + slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) + return slotHash +} + +func getLocMappingAtKey (key common.Hash, slot uint64) common.Hash { + slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) + return crypto.Keccak256Hash(key.Bytes(), slotHash.Bytes()) +} + +func getLocDynamicArrAtElement (slotHash common.Hash, index uint64, elementSize uint64) common.Hash { + slotKecBig := crypto.Keccak256Hash(slotHash.Bytes()).Big() + //arrBig = slotKecBig + index * elementSize + arrBig := slotKecBig.Add(slotKecBig, new(big.Int).SetUint64(index * elementSize)) + return common.BigToHash(arrBig) +} + +func getLocFixedArrAtElement (slot uint64, index uint64, elementSize uint64) common.Hash { + slotBig := new(big.Int).SetUint64(slot) + arrBig := slotBig.Add(slotBig, new(big.Int).SetUint64(index * elementSize)) + return common.BigToHash(arrBig) +} From f71616b08704d223cc1c8c47f9f853f713b4820c Mon Sep 17 00:00:00 2001 From: Tuna Date: Thu, 3 Jan 2019 16:40:23 +0700 Subject: [PATCH 03/21] add validator(smc) reader --- contracts/smcReader.go | 78 -------------------------- contracts/smcUtils.go | 18 +++--- contracts/validatorReader.go | 106 +++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 85 deletions(-) delete mode 100644 contracts/smcReader.go create mode 100644 contracts/validatorReader.go diff --git a/contracts/smcReader.go b/contracts/smcReader.go deleted file mode 100644 index 3392e1d6ea..0000000000 --- a/contracts/smcReader.go +++ /dev/null @@ -1,78 +0,0 @@ -package contracts - -import ( - "fmt" - "strings" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/contracts/blocksigner/contract" - "github.com/ethereum/go-ethereum/core/types" -) - -var ( - slotBlockSignerMapping = map[string]uint64{ - "getSigners": 0, - } - ParsedBlockSignerABI, _ = abi.JSON(strings.NewReader(contract.BlockSignerABI)) -) - -/////////////////////////////////////// -////// BlockSigner SMC /////////// -/////////////////////////////////////// -func GetSigners(statedb *state.StateDB, parsed abi.ABI, block *types.Block) ([]common.Address) { - methodName := "getSigners" - fmt.Printf("---%s---\n", methodName) - start := time.Now() - signers := getSigners(parsed, statedb, common.HexToAddress(common.BlockSigners), methodName, block.Hash()) - elapsed := time.Since(start) - fmt.Printf("Execution time: %s\n", elapsed) - return signers -} - -func getSigners(parsed abi.ABI, statedb *state.StateDB, address common.Address, methodName string, input ...common.Hash) ([]common.Address) { - keys := getKeys(statedb, address, parsed, methodName, input...) - rets := []common.Address{} - ret := common.Address{} - for _, key := range keys { - value := statedb.GetState(address, key) - method := parsed.Methods[methodName] - switch method.Outputs[0].Type.T { - case abi.AddressTy: - ret = common.BytesToAddress(value.Bytes()) - default: - err := parsed.Unpack(&ret, methodName, value.Bytes()) - if err != nil { - fmt.Printf("err: %v\n", err) - } - //ret = common.BytesToAddress(value.Bytes()) - } - rets = append(rets, ret) - } - return rets -} - -func getKeys(statedb *state.StateDB, address common.Address, parsed abi.ABI, methodName string, input ...common.Hash) ([]common.Hash) { - method, ok := parsed.Methods[methodName] - slot := slotBlockSignerMapping[methodName] - keys := []common.Hash{} - - // do not support function call - if ok && len(method.Inputs) <= 1 || len(method.Outputs) == 1 { - if len(method.Inputs) == 0 { - keys = append(keys, getLocSimpleVariable(slot)) - } else { - // support first input - keyArrSlot := getLocMappingAtKey(input[0], slot) - arrSlot := statedb.GetState(address, keyArrSlot) - arrLength := arrSlot.Big().Uint64() - for i := uint64(0); i < arrLength; i++ { - valueHash := getLocDynamicArrAtElement(keyArrSlot, i, 1) - keys = append(keys, valueHash) - } - } - } - return keys -} diff --git a/contracts/smcUtils.go b/contracts/smcUtils.go index da53c8d2e5..8c71c78164 100644 --- a/contracts/smcUtils.go +++ b/contracts/smcUtils.go @@ -2,29 +2,33 @@ package contracts import ( "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) -func getLocSimpleVariable (slot uint64) common.Hash { +func getLocSimpleVariable(slot uint64) common.Hash { slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) return slotHash } -func getLocMappingAtKey (key common.Hash, slot uint64) common.Hash { +func getLocMappingAtKey(key common.Hash, slot uint64) *big.Int { slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) - return crypto.Keccak256Hash(key.Bytes(), slotHash.Bytes()) + retByte := crypto.Keccak256(key.Bytes(), slotHash.Bytes()) + ret := new(big.Int) + ret.SetBytes(retByte) + return ret } -func getLocDynamicArrAtElement (slotHash common.Hash, index uint64, elementSize uint64) common.Hash { +func getLocDynamicArrAtElement(slotHash common.Hash, index uint64, elementSize uint64) common.Hash { slotKecBig := crypto.Keccak256Hash(slotHash.Bytes()).Big() //arrBig = slotKecBig + index * elementSize - arrBig := slotKecBig.Add(slotKecBig, new(big.Int).SetUint64(index * elementSize)) + arrBig := slotKecBig.Add(slotKecBig, new(big.Int).SetUint64(index*elementSize)) return common.BigToHash(arrBig) } -func getLocFixedArrAtElement (slot uint64, index uint64, elementSize uint64) common.Hash { +func getLocFixedArrAtElement(slot uint64, index uint64, elementSize uint64) common.Hash { slotBig := new(big.Int).SetUint64(slot) - arrBig := slotBig.Add(slotBig, new(big.Int).SetUint64(index * elementSize)) + arrBig := slotBig.Add(slotBig, new(big.Int).SetUint64(index*elementSize)) return common.BigToHash(arrBig) } diff --git a/contracts/validatorReader.go b/contracts/validatorReader.go new file mode 100644 index 0000000000..7d3267dc2f --- /dev/null +++ b/contracts/validatorReader.go @@ -0,0 +1,106 @@ +package contracts + +import ( + "fmt" + "math/big" + "strings" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + validatorContract "github.com/ethereum/go-ethereum/contracts/validator/contract" + "github.com/ethereum/go-ethereum/core/state" +) + +var ( + ParsedValidatorABI, _ = abi.JSON(strings.NewReader(validatorContract.TomoValidatorABI)) + slotValidatorMapping = map[string]uint64{ + "withdrawsState": 0, + "validatorsState": 1, + "voters": 2, + "candidates": 3, + "candidateCount": 4, + "minCandidateCap": 5, + "minVoterCap": 6, + "maxValidatorNumber": 7, + "candidateWithdrawDelay": 8, + "voterWithdrawDelay": 9, + } +) + +func GetCandidates(statedb *state.StateDB, parsed abi.ABI) []common.Address { + start := time.Now() + slot := slotValidatorMapping["candidates"] + slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) + arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), slotHash) + fmt.Printf("Candidates length: %v\n", arrLength.Hex()) + keys := []common.Hash{} + for i := uint64(0); i < arrLength.Big().Uint64(); i++ { + key := getLocDynamicArrAtElement(slotHash, i, 1) + keys = append(keys, key) + } + rets := []common.Address{} + for _, key := range keys { + ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), key) + rets = append(rets, common.HexToAddress(ret.Hex())) + fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) + } + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) + return rets +} + +func GetCandidateOwner(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) common.Address { + start := time.Now() + + slot := slotValidatorMapping["validatorsState"] + // validatorsState[_candidate].owner; + locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) + locCandidateOwner := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(0))) + ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locCandidateOwner)) + fmt.Printf("ret hex: %v\n", ret.Hex()) + + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) + return common.HexToAddress(ret.Hex()) +} + +func GetCandidateCap(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) string { + start := time.Now() + + slot := slotValidatorMapping["validatorsState"] + // validatorsState[_candidate].cap; + locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) + locCandidateCap := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(2))) + ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locCandidateCap)) + fmt.Printf("ret hex: %v\n", ret.Hex()) + + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) + return ret.Hex() +} + +func GetVoters(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) []common.Address { + start := time.Now() + + //mapping(address => address[]) voters; + slot := slotValidatorMapping["voters"] + locVoters := getLocMappingAtKey(candidate.Hash(), slot) + arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locVoters)) + fmt.Printf("Voters length: %v\n", arrLength.Hex()) + keys := []common.Hash{} + for i := uint64(0); i < arrLength.Big().Uint64(); i++ { + key := getLocDynamicArrAtElement(common.BigToHash(locVoters), i, 1) + keys = append(keys, key) + } + rets := []common.Address{} + for _, key := range keys { + ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), key) + rets = append(rets, common.HexToAddress(ret.Hex())) + fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) + } + + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) + return rets +} From cdb765449111770c52b66eba12155feaa2874893 Mon Sep 17 00:00:00 2001 From: Tuna Date: Thu, 3 Jan 2019 17:13:56 +0700 Subject: [PATCH 04/21] update blocksigner(smc) reader --- contracts/blockSignerReader.go | 46 ++++++++++++++++++++++++++++++++++ contracts/validatorReader.go | 4 ++- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 contracts/blockSignerReader.go diff --git a/contracts/blockSignerReader.go b/contracts/blockSignerReader.go new file mode 100644 index 0000000000..6a99c9a17d --- /dev/null +++ b/contracts/blockSignerReader.go @@ -0,0 +1,46 @@ +package contracts + +import ( + "fmt" + "strings" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + blockSignerContract "github.com/ethereum/go-ethereum/contracts/blocksigner/contract" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" +) + +var ( + slotBlockSignerMapping = map[string]uint64{ + "blockSigners": 0, + "blocks": 1, + } + ParsedBlockSignerABI, _ = abi.JSON(strings.NewReader(blockSignerContract.BlockSignerABI)) +) + +func GetSigners(statedb *state.StateDB, parsed abi.ABI, block *types.Block) []common.Address { + methodName := "getSigners" + fmt.Printf("---%s---\n", methodName) + start := time.Now() + slot := slotBlockSignerMapping["blockSigners"] + keys := []common.Hash{} + keyArrSlot := getLocMappingAtKey(block.Hash(), slot) + arrSlot := statedb.GetState(common.HexToAddress(common.BlockSigners), common.BigToHash(keyArrSlot)) + arrLength := arrSlot.Big().Uint64() + for i := uint64(0); i < arrLength; i++ { + key := getLocDynamicArrAtElement(common.BigToHash(keyArrSlot), i, 1) + keys = append(keys, key) + } + rets := []common.Address{} + for _, key := range keys { + ret := statedb.GetState(common.HexToAddress(common.BlockSigners), key) + rets = append(rets, common.HexToAddress(ret.Hex())) + fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) + } + + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) + return rets +} diff --git a/contracts/validatorReader.go b/contracts/validatorReader.go index 7d3267dc2f..0cd081afa1 100644 --- a/contracts/validatorReader.go +++ b/contracts/validatorReader.go @@ -52,13 +52,14 @@ func GetCandidates(statedb *state.StateDB, parsed abi.ABI) []common.Address { func GetCandidateOwner(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) common.Address { start := time.Now() + fmt.Printf("--------GetCandidateOwner---------\n") slot := slotValidatorMapping["validatorsState"] // validatorsState[_candidate].owner; locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) locCandidateOwner := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(0))) ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locCandidateOwner)) - fmt.Printf("ret hex: %v\n", ret.Hex()) + fmt.Printf("ret: %v\n", common.HexToAddress(ret.Hex()).Hex()) elapsed := time.Since(start) fmt.Printf("Execution time: %s\n", elapsed) @@ -82,6 +83,7 @@ func GetCandidateCap(statedb *state.StateDB, parsed abi.ABI, candidate common.Ad func GetVoters(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) []common.Address { start := time.Now() + fmt.Printf("--------GetVoters---------\n") //mapping(address => address[]) voters; slot := slotValidatorMapping["voters"] From 17ba9229101733838ca35a10b1e218249bc42586 Mon Sep 17 00:00:00 2001 From: Tuna Date: Thu, 3 Jan 2019 18:20:25 +0700 Subject: [PATCH 05/21] add randomize(smc) reader --- contracts/randomizeReader.go | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 contracts/randomizeReader.go diff --git a/contracts/randomizeReader.go b/contracts/randomizeReader.go new file mode 100644 index 0000000000..5b68109bbd --- /dev/null +++ b/contracts/randomizeReader.go @@ -0,0 +1,58 @@ +package contracts + +import ( + "fmt" + "strings" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + randomizeContract "github.com/ethereum/go-ethereum/contracts/randomize/contract" + "github.com/ethereum/go-ethereum/core/state" +) + +var ( + slotRandomizeMapping = map[string]uint64{ + "randomSecret": 0, + "randomOpening": 1, + } + ParsedRandomizeABI, _ = abi.JSON(strings.NewReader(randomizeContract.TomoRandomizeABI)) +) + +func GetSecret(statedb *state.StateDB, parsed abi.ABI, address common.Address) [][]byte { + start := time.Now() + fmt.Printf("--------GetSecret---------\n") + + slot := slotRandomizeMapping["randomSecret"] + locSecret := getLocMappingAtKey(address.Hash(), slot) + arrLength := statedb.GetState(common.HexToAddress(common.RandomizeSMC), common.BigToHash(locSecret)) + fmt.Printf("Secret length: %v\n", arrLength.Hex()) + keys := []common.Hash{} + for i := uint64(0); i < arrLength.Big().Uint64(); i++ { + key := getLocDynamicArrAtElement(common.BigToHash(locSecret), i, 1) + keys = append(keys, key) + } + rets := [][]byte{} + for _, key := range keys { + ret := statedb.GetState(common.HexToAddress(common.RandomizeSMC), key) + rets = append(rets, ret.Bytes()) + fmt.Printf("ret hex: %v - ret byte: %v\n", ret.Hex(), ret.Bytes()) + } + elapsed := time.Since(start) + + fmt.Printf("Execution time: %s\n", elapsed) + return rets +} + +func GetOpening(statedb *state.StateDB, parsed abi.ABI, address common.Address) []byte { + start := time.Now() + fmt.Printf("--------GetOpening---------\n") + + slot := slotRandomizeMapping["randomOpening"] + locOpening := getLocMappingAtKey(address.Hash(), slot) + ret := statedb.GetState(common.HexToAddress(common.RandomizeSMC), common.BigToHash(locOpening)) + fmt.Printf("ret hex: %v - ret byte: %v\n", ret.Hex(), ret.Bytes()) + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) + return ret.Bytes() +} From 237111a5ba3eb2ceae9498f964fdb6af932734eb Mon Sep 17 00:00:00 2001 From: Tuna Date: Sat, 5 Jan 2019 16:25:23 +0700 Subject: [PATCH 06/21] modify logic to adapt new readers --- consensus/posv/posv.go | 22 +++++---- contracts/blockSignerReader.go | 2 +- contracts/randomizeReader.go | 10 ++-- contracts/utils.go | 87 ++++++++-------------------------- contracts/validatorReader.go | 4 +- eth/backend.go | 63 ++++++++---------------- internal/ethapi/api.go | 15 +++--- 7 files changed, 68 insertions(+), 135 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index a6f0613954..54fbddf1b8 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -224,10 +224,10 @@ type Posv struct { signFn clique.SignerFn // Signer function to authorize hashes with lock sync.RWMutex // Protects the signer fields - HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) - HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) - HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) - HookVerifyMNs func(header *types.Header, signers []common.Address) error + HookReward func(state *state.StateDB, chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) + HookPenalty func(state *state.StateDB, chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) + HookValidator func(state *state.StateDB, header *types.Header, signers []common.Address) ([]byte, error) + HookVerifyMNs func(state *state.StateDB, header *types.Header, signers []common.Address) error } // New creates a PoSV proof-of-stake-voting consensus engine with the initial @@ -390,9 +390,11 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types. } // If the block is a checkpoint block, verify the signer list if number%c.config.Epoch == 0 { + database := state.NewDatabase(c.db) + state, _ := state.New(parent.Hash(), database) penPenalties := []common.Address{} if c.HookPenalty != nil { - penPenalties, err = c.HookPenalty(chain, number) + penPenalties, err = c.HookPenalty(state, chain, number) if err != nil { return err } @@ -417,7 +419,7 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types. return errInvalidCheckpointSigners } if c.HookVerifyMNs != nil { - err := c.HookVerifyMNs(header, signers) + err := c.HookVerifyMNs(state, header, signers) if err != nil { return err } @@ -775,8 +777,10 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error header.Extra = header.Extra[:extraVanity] masternodes := snap.GetSigners() if number > 0 && number%c.config.Epoch == 0 { + database := state.NewDatabase(c.db) + state, _ := state.New(parent.Hash(), database) if c.HookPenalty != nil { - penMasternodes, err := c.HookPenalty(chain, number) + penMasternodes, err := c.HookPenalty(state, chain, number) if err != nil { return err } @@ -799,7 +803,7 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error header.Extra = append(header.Extra, masternode[:]...) } if c.HookValidator != nil { - validators, err := c.HookValidator(header, masternodes) + validators, err := c.HookValidator(state, header, masternodes) if err != nil { return err } @@ -850,7 +854,7 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state rCheckpoint := chain.Config().Posv.RewardCheckpoint if c.HookReward != nil && number%rCheckpoint == 0 { - err, rewards := c.HookReward(chain, state, header) + err, rewards := c.HookReward(state, chain, header) if err != nil { return nil, err } diff --git a/contracts/blockSignerReader.go b/contracts/blockSignerReader.go index 6a99c9a17d..f270589d5d 100644 --- a/contracts/blockSignerReader.go +++ b/contracts/blockSignerReader.go @@ -20,7 +20,7 @@ var ( ParsedBlockSignerABI, _ = abi.JSON(strings.NewReader(blockSignerContract.BlockSignerABI)) ) -func GetSigners(statedb *state.StateDB, parsed abi.ABI, block *types.Block) []common.Address { +func GetSigners(statedb *state.StateDB, block *types.Block) []common.Address { methodName := "getSigners" fmt.Printf("---%s---\n", methodName) start := time.Now() diff --git a/contracts/randomizeReader.go b/contracts/randomizeReader.go index 5b68109bbd..fd2d4bc3a0 100644 --- a/contracts/randomizeReader.go +++ b/contracts/randomizeReader.go @@ -19,7 +19,7 @@ var ( ParsedRandomizeABI, _ = abi.JSON(strings.NewReader(randomizeContract.TomoRandomizeABI)) ) -func GetSecret(statedb *state.StateDB, parsed abi.ABI, address common.Address) [][]byte { +func GetSecret(statedb *state.StateDB, address common.Address) [][32]byte { start := time.Now() fmt.Printf("--------GetSecret---------\n") @@ -32,10 +32,10 @@ func GetSecret(statedb *state.StateDB, parsed abi.ABI, address common.Address) [ key := getLocDynamicArrAtElement(common.BigToHash(locSecret), i, 1) keys = append(keys, key) } - rets := [][]byte{} + rets := [][32]byte{} for _, key := range keys { ret := statedb.GetState(common.HexToAddress(common.RandomizeSMC), key) - rets = append(rets, ret.Bytes()) + rets = append(rets, ret) fmt.Printf("ret hex: %v - ret byte: %v\n", ret.Hex(), ret.Bytes()) } elapsed := time.Since(start) @@ -44,7 +44,7 @@ func GetSecret(statedb *state.StateDB, parsed abi.ABI, address common.Address) [ return rets } -func GetOpening(statedb *state.StateDB, parsed abi.ABI, address common.Address) []byte { +func GetOpening(statedb *state.StateDB, address common.Address) [32]byte { start := time.Now() fmt.Printf("--------GetOpening---------\n") @@ -54,5 +54,5 @@ func GetOpening(statedb *state.StateDB, parsed abi.ABI, address common.Address) fmt.Printf("ret hex: %v - ret byte: %v\n", ret.Hex(), ret.Bytes()) elapsed := time.Since(start) fmt.Printf("Execution time: %s\n", elapsed) - return ret.Bytes() + return ret } diff --git a/contracts/utils.go b/contracts/utils.go index faf86b1c55..ad7feaeff8 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -31,14 +31,10 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/posv" - "github.com/ethereum/go-ethereum/contracts/blocksigner/contract" - randomizeContract "github.com/ethereum/go-ethereum/contracts/randomize/contract" - contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -199,41 +195,14 @@ func BuildTxOpeningRandomize(nonce uint64, randomizeAddr common.Address, randomi } // Get signers signed for blockNumber from blockSigner contract. -func GetSignersFromContract(addrBlockSigner common.Address, client bind.ContractBackend, blockHash common.Hash) ([]common.Address, error) { - blockSigner, err := contract.NewBlockSigner(addrBlockSigner, client) - if err != nil { - log.Error("Fail get instance of blockSigner", "error", err) - return nil, err - } - opts := new(bind.CallOpts) - addrs, err := blockSigner.GetSigners(opts, blockHash) - if err != nil { - log.Error("Fail get block signers", "error", err) - return nil, err - } - - return addrs, nil +func GetSignersFromContract(state *state.StateDB, block *types.Block) ([]common.Address, error) { + return GetSigners(state, block), nil } // Get random from randomize contract. -func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common.Address) (int64, error) { - randomize, err := randomizeContract.NewTomoRandomize(common.HexToAddress(common.RandomizeSMC), client) - if err != nil { - log.Error("Fail to get instance of randomize", "error", err) - return -1, err - } - opts := new(bind.CallOpts) - secrets, err := randomize.GetSecret(opts, addrMasternode) - if err != nil { - log.Error("Fail get secrets from randomize", "error", err) - return -1, err - } - opening, err := randomize.GetOpening(opts, addrMasternode) - if err != nil { - log.Error("Fail get opening from randomize", "error", err) - return -1, err - } - +func GetRandomizeFromContract(state *state.StateDB, addrMasternode common.Address) (int64, error) { + secrets := GetSecret(state, addrMasternode) + opening := GetOpening(state, addrMasternode) return DecryptRandomizeFromSecretsAndOpening(secrets, opening) } @@ -306,8 +275,7 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte) return random, nil } -// Calculate reward for reward checkpoint. -func GetRewardForCheckpoint(chain consensus.ChainReader, blockSignerAddr common.Address, number uint64, rCheckpoint uint64, client bind.ContractBackend, totalSigner *uint64) (map[common.Address]*rewardLog, error) { +func GetRewardForCheckpoint(chain consensus.ChainReader, number uint64, rCheckpoint uint64, totalSigner *uint64, state *state.StateDB) (map[common.Address]*rewardLog, error) { // Not reward for singer of genesis block and only calculate reward at checkpoint block. prevCheckpoint := number - (rCheckpoint * 2) startBlockNumber := prevCheckpoint + 1 @@ -318,8 +286,10 @@ func GetRewardForCheckpoint(chain consensus.ChainReader, blockSignerAddr common. if len(masternodes) > 0 { for i := startBlockNumber; i <= endBlockNumber; i++ { - block := chain.GetHeaderByNumber(i) - addrs, err := GetSignersFromContract(blockSignerAddr, client, block.Hash()) + bheader := chain.GetHeaderByNumber(i) + bhash := bheader.Hash() + block := chain.GetBlock(bhash, i) + addrs, err := GetSignersFromContract(state, block) if err != nil { log.Error("Fail to get signers from smartcontract.", "error", err, "blockNumber", i) return nil, err @@ -382,21 +352,13 @@ func CalculateRewardForSigner(chainReward *big.Int, signers map[common.Address]* } // Get candidate owner by address. -func GetCandidatesOwnerBySigner(validator *contractValidator.TomoValidator, signerAddr common.Address) common.Address { - owner := signerAddr - opts := new(bind.CallOpts) - owner, err := validator.GetCandidateOwner(opts, signerAddr) - if err != nil { - log.Error("Fail get candidate owner", "error", err) - return owner - } - +func GetCandidatesOwnerBySigner(state *state.StateDB, signerAddr common.Address) common.Address { + owner := GetCandidateOwner(state, signerAddr) return owner } -// Calculate reward for holders. -func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *contractValidator.TomoValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) (error, map[common.Address]*big.Int) { - rewards, err := GetRewardBalancesRate(foudationWalletAddr, signer, calcReward, validator) +func CalculateRewardForHolders(foundationWalletAddr common.Address, state *state.StateDB, signer common.Address, calcReward *big.Int) (error, map[common.Address]*big.Int) { + rewards, err := GetRewardBalancesRate(foundationWalletAddr, state, signer, calcReward) if err != nil { return err, nil } @@ -407,21 +369,14 @@ func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *co } return nil, rewards } - -// Get reward balance rates for master node, founder and holders. -func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common.Address, totalReward *big.Int, validator *contractValidator.TomoValidator) (map[common.Address]*big.Int, error) { - owner := GetCandidatesOwnerBySigner(validator, masterAddr) +func GetRewardBalancesRate(foundationWalletAddr common.Address, state *state.StateDB, masterAddr common.Address, totalReward *big.Int) (map[common.Address]*big.Int, error) { + owner := GetCandidatesOwnerBySigner(state, masterAddr) balances := make(map[common.Address]*big.Int) rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent)) rewardMaster = new(big.Int).Div(rewardMaster, new(big.Int).SetInt64(100)) balances[owner] = rewardMaster // Get voters for masternode. - opts := new(bind.CallOpts) - voters, err := validator.GetVoters(opts, masterAddr) - if err != nil { - log.Error("Fail to get voters", "error", err) - return nil, err - } + voters := GetVoters(state, masterAddr) if len(voters) > 0 { totalVoterReward := new(big.Int).Mul(totalReward, new(big.Int).SetUint64(common.RewardVoterPercent)) @@ -430,7 +385,7 @@ func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common // Get voters capacities. voterCaps := make(map[common.Address]*big.Int) for _, voteAddr := range voters { - voterCap, err := validator.GetVoterCap(opts, masterAddr, voteAddr) + voterCap, err := GetVoterCap(state, masterAddr, voteAddr) if err != nil { log.Error("Fail to get vote capacity", "error", err) return nil, err @@ -455,9 +410,9 @@ func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common } } - foudationReward := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardFoundationPercent)) - foudationReward = new(big.Int).Div(foudationReward, new(big.Int).SetInt64(100)) - balances[foudationWalletAddr] = foudationReward + foundationReward := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardFoundationPercent)) + foundationReward = new(big.Int).Div(foundationReward, new(big.Int).SetInt64(100)) + balances[foundationWalletAddr] = foundationReward jsonHolders, err := json.Marshal(balances) if err != nil { diff --git a/contracts/validatorReader.go b/contracts/validatorReader.go index 0cd081afa1..b8b1ea2a84 100644 --- a/contracts/validatorReader.go +++ b/contracts/validatorReader.go @@ -50,7 +50,7 @@ func GetCandidates(statedb *state.StateDB, parsed abi.ABI) []common.Address { return rets } -func GetCandidateOwner(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) common.Address { +func GetCandidateOwner(statedb *state.StateDB, candidate common.Address) common.Address { start := time.Now() fmt.Printf("--------GetCandidateOwner---------\n") @@ -81,7 +81,7 @@ func GetCandidateCap(statedb *state.StateDB, parsed abi.ABI, candidate common.Ad return ret.Hex() } -func GetVoters(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) []common.Address { +func GetVoters(statedb *state.StateDB, candidate common.Address) []common.Address { start := time.Now() fmt.Printf("--------GetVoters---------\n") diff --git a/eth/backend.go b/eth/backend.go index ca31035aee..2553de199a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -34,7 +34,6 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/posv" "github.com/ethereum/go-ethereum/contracts" - "github.com/ethereum/go-ethereum/contracts/validator/contract" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/state" @@ -231,9 +230,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { eth.protocolManager.fetcher.SetAppendM2HeaderHook(appendM2HeaderHook) // Hook prepares validators M2 for the current epoch at checkpoint block - c.HookValidator = func(header *types.Header, signers []common.Address) ([]byte, error) { + c.HookValidator = func(state *state.StateDB, header *types.Header, signers []common.Address) ([]byte, error) { start := time.Now() - validators, err := GetValidators(eth.blockchain, signers) + validators, err := GetValidators(state, signers) if err != nil { return []byte{}, err } @@ -243,23 +242,20 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } // Hook scans for bad masternodes and decide to penalty them - c.HookPenalty = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) { - client, err := eth.blockchain.GetClient() - if err != nil { - return nil, err - } + c.HookPenalty = func(state *state.StateDB, chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) { prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch if prevEpoc >= 0 { start := time.Now() prevHeader := chain.GetHeaderByNumber(prevEpoc) penSigners := c.GetMasternodes(chain, prevHeader) if len(penSigners) > 0 { - blockSignerAddr := common.HexToAddress(common.BlockSigners) // Loop for each block to check missing sign. for i := prevEpoc; i < blockNumberEpoc; i++ { - blockHeader := chain.GetHeaderByNumber(i) + bHeader := chain.GetHeaderByNumber(i) + bHash := bHeader.Hash() + block := chain.GetBlock(bHash, i) if len(penSigners) > 0 { - signedMasternodes, err := contracts.GetSignersFromContract(blockSignerAddr, client, blockHeader.Hash()) + signedMasternodes, err := contracts.GetSignersFromContract(state, block) if err != nil { return nil, err } @@ -286,28 +282,25 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } // Hook calculates reward for masternodes - c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) { - client, err := eth.blockchain.GetClient() - if err != nil { - log.Crit("Fail to connect IPC client for blockSigner", "error", err) - } + c.HookReward = func(state *state.StateDB, chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) { number := header.Number.Uint64() rCheckpoint := chain.Config().Posv.RewardCheckpoint - foudationWalletAddr := chain.Config().Posv.FoudationWalletAddr - if foudationWalletAddr == (common.Address{}) { - log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr) + foundationWalletAddr := chain.Config().Posv.FoudationWalletAddr + if foundationWalletAddr == (common.Address{}) { + log.Error("Foundation Wallet Address is empty", "error", foundationWalletAddr) + return err, nil } rewards := make(map[string]interface{}) - if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) { + if number > 0 && number-rCheckpoint > 0 && foundationWalletAddr != (common.Address{}) { start := time.Now() // Get signers in blockSigner smartcontract. - addr := common.HexToAddress(common.BlockSigners) // Get reward inflation. chainReward := new(big.Int).Mul(new(big.Int).SetUint64(chain.Config().Posv.Reward), new(big.Int).SetUint64(params.Ether)) chainReward = rewardInflation(chainReward, number, common.BlocksPerYear) totalSigner := new(uint64) - signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner) + signers, err := contracts.GetRewardForCheckpoint(chain, number, rCheckpoint, totalSigner, state) + log.Debug("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) if err != nil { log.Crit("Fail to get signers for reward checkpoint", "error", err) } @@ -316,16 +309,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if err != nil { log.Crit("Fail to calculate reward for signers", "error", err) } - // Get validator. - validator, err := contract.NewTomoValidator(common.HexToAddress(common.MasternodeVotingSMC), client) - if err != nil { - log.Crit("Fail get instance of Tomo Validator", "error", err) - } // Add reward for coin holders. voterResults := make(map[common.Address]interface{}) if len(signers) > 0 { for signer, calcReward := range rewardSigners { - err, rewards := contracts.CalculateRewardForHolders(foudationWalletAddr, validator, state, signer, calcReward) + err, rewards := contracts.CalculateRewardForHolders(foundationWalletAddr, state, signer, calcReward) if err != nil { log.Crit("Fail to calculate reward for holders.", "error", err) } @@ -339,11 +327,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } // Hook verifies masternodes set - c.HookVerifyMNs = func(header *types.Header, signers []common.Address) error { + c.HookVerifyMNs = func(state *state.StateDB, header *types.Header, signers []common.Address) error { number := header.Number.Int64() if number > 0 && number%common.EpocBlockRandomize == 0 { start := time.Now() - validators, err := GetValidators(eth.blockchain, signers) + validators, err := GetValidators(state, signers) log.Debug("Time Calculated HookVerifyMNs ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) if err != nil { return err @@ -642,25 +630,14 @@ func (s *Ethereum) Stop() error { return nil } -func GetValidators(bc *core.BlockChain, masternodes []common.Address) ([]byte, error) { - if bc.Config().Posv == nil { - return nil, core.ErrNotPoSV - } - client, err := bc.GetClient() - if err != nil { - return nil, err - } +func GetValidators(state *state.StateDB, masternodes []common.Address) ([]byte, error) { // Check m2 exists on chaindb. // Get secrets and opening at epoc block checkpoint. - var candidates []int64 - if err != nil { - return nil, err - } lenSigners := int64(len(masternodes)) if lenSigners > 0 { for _, addr := range masternodes { - random, err := contracts.GetRandomizeFromContract(client, addr) + random, err := contracts.GetRandomizeFromContract(state, addr) if err != nil { return nil, err } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f9ec6ad29a..8e384da6c5 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -855,21 +855,18 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx } fields["uncles"] = uncleHashes - // Get signers for block. - client, err := s.b.GetIPCClient() - if err != nil { - log.Error("Fail to connect IPC client for block status", "error", err) - return nil, err - } var signers []common.Address var filterSigners []common.Address finality := int32(0) if b.Number().Int64() > 0 { - addrBlockSigner := common.HexToAddress(common.BlockSigners) - signers, err = contracts.GetSignersFromContract(addrBlockSigner, client, b.Hash()) + blockNr := rpc.BlockNumber(b.Number().Int64()) + state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) + if state == nil || err != nil { + return nil, err + } + signers, err = contracts.GetSignersFromContract(state, b) if err != nil { log.Error("Fail to get signers from block signer SC.", "error", err) - return nil, err } // Get block epoc latest. if s.b.ChainConfig().Posv != nil { From b7306c639e05eefa3d5822abbd3297672d2cf14e Mon Sep 17 00:00:00 2001 From: Tuna Date: Sat, 5 Jan 2019 16:43:46 +0700 Subject: [PATCH 07/21] add GetVoterCap func --- contracts/utils.go | 7 +------ contracts/validatorReader.go | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/contracts/utils.go b/contracts/utils.go index ad7feaeff8..e04418df5e 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -385,12 +385,7 @@ func GetRewardBalancesRate(foundationWalletAddr common.Address, state *state.Sta // Get voters capacities. voterCaps := make(map[common.Address]*big.Int) for _, voteAddr := range voters { - voterCap, err := GetVoterCap(state, masterAddr, voteAddr) - if err != nil { - log.Error("Fail to get vote capacity", "error", err) - return nil, err - } - + voterCap := GetVoterCap(state, masterAddr, voteAddr) totalCap.Add(totalCap, voterCap) voterCaps[voteAddr] = voterCap } diff --git a/contracts/validatorReader.go b/contracts/validatorReader.go index b8b1ea2a84..7318487f6c 100644 --- a/contracts/validatorReader.go +++ b/contracts/validatorReader.go @@ -106,3 +106,17 @@ func GetVoters(statedb *state.StateDB, candidate common.Address) []common.Addres fmt.Printf("Execution time: %s\n", elapsed) return rets } + +func GetVoterCap(state *state.StateDB, candidate, voter common.Address) *big.Int { + //validatorsState[_candidate].voters[_voter] + start := time.Now() + fmt.Printf("--------GetVoterCap---------\n") + slot := slotValidatorMapping["validatorsState"] + locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) + locCandidateVoters := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(3))) + locVoters := getLocMappingAtKey(voter.Hash(), locCandidateVoters.Uint64()) + ret := state.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locVoters)) + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) + return ret.Big() +} From c7144977e40279ee8c46aa43fe4f7fd83259e727 Mon Sep 17 00:00:00 2001 From: Tuna Date: Mon, 7 Jan 2019 17:21:07 +0700 Subject: [PATCH 08/21] fix GetVoterCap --- contracts/validatorReader.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/contracts/validatorReader.go b/contracts/validatorReader.go index 7318487f6c..e471ae31fd 100644 --- a/contracts/validatorReader.go +++ b/contracts/validatorReader.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" validatorContract "github.com/ethereum/go-ethereum/contracts/validator/contract" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/crypto" ) var ( @@ -72,7 +73,7 @@ func GetCandidateCap(statedb *state.StateDB, parsed abi.ABI, candidate common.Ad slot := slotValidatorMapping["validatorsState"] // validatorsState[_candidate].cap; locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) - locCandidateCap := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(2))) + locCandidateCap := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(1))) ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locCandidateCap)) fmt.Printf("ret hex: %v\n", ret.Hex()) @@ -113,9 +114,10 @@ func GetVoterCap(state *state.StateDB, candidate, voter common.Address) *big.Int fmt.Printf("--------GetVoterCap---------\n") slot := slotValidatorMapping["validatorsState"] locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) - locCandidateVoters := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(3))) - locVoters := getLocMappingAtKey(voter.Hash(), locCandidateVoters.Uint64()) - ret := state.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locVoters)) + locCandidateVoters := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(2))) + retByte := crypto.Keccak256(voter.Hash().Bytes(), common.BigToHash(locCandidateVoters).Bytes()) + ret := state.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BytesToHash(retByte)) + fmt.Printf("voter: %v - cap: %v\n", voter.Hex(), ret.Big().String()) elapsed := time.Since(start) fmt.Printf("Execution time: %s\n", elapsed) return ret.Big() From 206fcfd8b67381126075fd5cc1f00e51f051e6e1 Mon Sep 17 00:00:00 2001 From: Tuna Date: Tue, 8 Jan 2019 14:51:52 +0700 Subject: [PATCH 09/21] add state variable to verifyHeader(), verifyHeaders() in the consensus interface --- cmd/utils/flags.go | 25 +++++++++++----------- consensus/consensus.go | 6 +++--- consensus/posv/posv.go | 26 ++++++++++------------- core/blockchain.go | 18 +++++++++++++--- core/headerchain.go | 5 +++-- eth/api_tracer.go | 6 +++++- eth/backend.go | 48 ++++++++++++++++++++++-------------------- eth/handler.go | 6 +++++- light/lightchain.go | 6 +++++- miner/worker.go | 2 +- 10 files changed, 86 insertions(+), 62 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index fbeecee31a..5aac42b208 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -33,7 +33,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/ethash" + //"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/posv" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -1245,17 +1245,18 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai if config.Posv != nil { engine = posv.New(config.Posv, chainDb) } else { - engine = ethash.NewFaker() - if !ctx.GlobalBool(FakePoWFlag.Name) { - engine = ethash.New(ethash.Config{ - CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir), - CachesInMem: eth.DefaultConfig.Ethash.CachesInMem, - CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk, - DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir), - DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem, - DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, - }) - } + //engine = ethash.NewFaker() + //if !ctx.GlobalBool(FakePoWFlag.Name) { + // engine = ethash.New(ethash.Config{ + // CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir), + // CachesInMem: eth.DefaultConfig.Ethash.CachesInMem, + // CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk, + // DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir), + // DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem, + // DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, + // }) + //} + Fatalf("Only support posv consensus") } if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) diff --git a/consensus/consensus.go b/consensus/consensus.go index b02afa63c4..8d992b5dee 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -58,13 +58,13 @@ type Engine interface { // VerifyHeader checks whether a header conforms to the consensus rules of a // given engine. Verifying the seal may be done optionally here, or explicitly // via the VerifySeal method. - VerifyHeader(chain ChainReader, header *types.Header, fullVerify bool) error + VerifyHeader(chain ChainReader, state *state.StateDB, header *types.Header, fullVerify bool) error // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers // concurrently. The method returns a quit channel to abort the operations and // a results channel to retrieve the async verifications (the order is that of // the input slice). - VerifyHeaders(chain ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) + VerifyHeaders(chain ChainReader, state *state.StateDB, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) // VerifyUncles verifies that the given block's uncles conform to the consensus // rules of a given engine. @@ -76,7 +76,7 @@ type Engine interface { // Prepare initializes the consensus fields of a block header according to the // rules of a particular engine. The changes are executed inline. - Prepare(chain ChainReader, header *types.Header) error + Prepare(chain ChainReader, state *state.StateDB, header *types.Header) error // Finalize runs any post-transaction state modifications (e.g. block rewards) // and assembles the final block. diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index 54fbddf1b8..b86028cce0 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -261,20 +261,20 @@ func (c *Posv) Author(header *types.Header) (common.Address, error) { } // VerifyHeader checks whether a header conforms to the consensus rules. -func (c *Posv) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error { - return c.verifyHeaderWithCache(chain, header, nil, fullVerify) +func (c *Posv) VerifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, fullVerify bool) error { + return c.verifyHeaderWithCache(chain, state, header, nil, fullVerify) } // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The // method returns a quit channel to abort the operations and a results channel to // retrieve the async verifications (the order is that of the input slice). -func (c *Posv) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) { +func (c *Posv) VerifyHeaders(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) { abort := make(chan struct{}) results := make(chan error, len(headers)) go func() { for i, header := range headers { - err := c.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i]) + err := c.verifyHeaderWithCache(chain, state, header, headers[:i], fullVerifies[i]) select { case <-abort: @@ -286,12 +286,12 @@ func (c *Posv) VerifyHeaders(chain consensus.ChainReader, headers []*types.Heade return abort, results } -func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { +func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error { _, check := c.verifiedHeaders.Get(header.Hash()) if check { return nil } - err := c.verifyHeader(chain, header, parents, fullVerify) + err := c.verifyHeader(chain, state, header, parents, fullVerify) if err == nil { c.verifiedHeaders.Add(header.Hash(), true) } @@ -302,7 +302,7 @@ func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types. // caller may optionally pass in a batch of parents (ascending order) to avoid // looking those up from the database. This is useful for concurrently verifying // a batch of new headers. -func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { +func (c *Posv) verifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error { if header.Number == nil { return errUnknownBlock } @@ -357,14 +357,14 @@ func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, p return err } // All basic checks passed, verify cascading fields - return c.verifyCascadingFields(chain, header, parents, fullVerify) + return c.verifyCascadingFields(chain, state, header, parents, fullVerify) } // verifyCascadingFields verifies all the header fields that are not standalone, // rather depend on a batch of previous headers. The caller may optionally pass // in a batch of parents (ascending order) to avoid looking those up from the // database. This is useful for concurrently verifying a batch of new headers. -func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { +func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error { // The genesis block is the always valid dead-end number := header.Number.Uint64() if number == 0 { @@ -390,8 +390,6 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types. } // If the block is a checkpoint block, verify the signer list if number%c.config.Epoch == 0 { - database := state.NewDatabase(c.db) - state, _ := state.New(parent.Hash(), database) penPenalties := []common.Address{} if c.HookPenalty != nil { penPenalties, err = c.HookPenalty(state, chain, number) @@ -541,7 +539,7 @@ func (c *Posv) snapshot(chain consensus.ChainReader, number uint64, hash common. // If we're at block zero, make a snapshot if number == 0 { genesis := chain.GetHeaderByNumber(0) - if err := c.VerifyHeader(chain, genesis, true); err != nil { + if err := c.VerifyHeader(chain, nil, genesis, true); err != nil { return nil, err } signers := make([]common.Address, (len(genesis.Extra)-extraVanity-extraSeal)/common.AddressLength) @@ -731,7 +729,7 @@ func (c *Posv) GetValidator(creator common.Address, chain consensus.ChainReader, // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. -func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error { +func (c *Posv) Prepare(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error { // If the block isn't a checkpoint, cast a random vote (good enough for now) header.Coinbase = common.Address{} header.Nonce = types.BlockNonce{} @@ -777,8 +775,6 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error header.Extra = header.Extra[:extraVanity] masternodes := snap.GetSigners() if number > 0 && number%c.config.Epoch == 0 { - database := state.NewDatabase(c.db) - state, _ := state.New(parent.Hash(), database) if c.HookPenalty != nil { penMasternodes, err := c.HookPenalty(state, chain, number) if err != nil { diff --git a/core/blockchain.go b/core/blockchain.go index 4d6c2cc011..46d9739ffb 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1069,7 +1069,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty seals[i] = true bc.downloadingBlock.Add(block.Hash(), true) } - abort, results := bc.engine.VerifyHeaders(bc, headers, seals) + st, err := bc.State() + if err != nil { + return 0, nil, nil, err + } + abort, results := bc.engine.VerifyHeaders(bc, st, headers, seals) defer close(abort) // Iterate over the blocks and insert when the verifier permits @@ -1246,7 +1250,11 @@ func (bc *BlockChain) PrepareBlock(block *types.Block) (err error) { log.Debug("Stop prepare a block because inserting", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.Header().Validator) return nil } - err = bc.engine.VerifyHeader(bc, block.Header(), false) + state, err := bc.State() + if err != nil { + return err + } + err = bc.engine.VerifyHeader(bc, state, block.Header(), false) if err != nil { return err } @@ -1678,7 +1686,11 @@ Error: %v // because nonces can be verified sparsely, not needing to check each. func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { start := time.Now() - if i, err := bc.hc.ValidateHeaderChain(chain, checkFreq); err != nil { + state, err := bc.State() + if err != nil { + return 0, err + } + if i, err := bc.hc.ValidateHeaderChain(chain, state, checkFreq); err != nil { return i, err } diff --git a/core/headerchain.go b/core/headerchain.go index 2d1b0a2a18..f0ecd73868 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/hashicorp/golang-lru" + "github.com/ethereum/go-ethereum/core/state" ) const ( @@ -203,7 +204,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er // header writes should be protected by the parent chain mutex individually. type WhCallback func(*types.Header) error -func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) (int, error) { +func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, state *state.StateDB, checkFreq int) (int, error) { // Do a sanity check that the provided chain is actually ordered and linked for i := 1; i < len(chain); i++ { if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() { @@ -227,7 +228,7 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) } seals[len(seals)-1] = true // Last should always be verified to avoid junk - abort, results := hc.engine.VerifyHeaders(hc, chain, seals) + abort, results := hc.engine.VerifyHeaders(hc, state, chain, seals) defer close(abort) // Iterate over the headers and ensure they all check out diff --git a/eth/api_tracer.go b/eth/api_tracer.go index 07c4457bc3..5f992494b0 100644 --- a/eth/api_tracer.go +++ b/eth/api_tracer.go @@ -387,7 +387,11 @@ func (api *PrivateDebugAPI) TraceBlockFromFile(ctx context.Context, file string, // per transaction, dependent on the requestd tracer. func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) { // Create the parent state database - if err := api.eth.engine.VerifyHeader(api.eth.blockchain, block.Header(), true); err != nil { + state, err := api.eth.blockchain.State() + if err != nil { + return nil, err + } + if err = api.eth.engine.VerifyHeader(api.eth.blockchain, state, block.Header(), true); err != nil { return nil, err } parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) diff --git a/eth/backend.go b/eth/backend.go index 2553de199a..ad58f0677c 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -393,29 +393,31 @@ func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chai if chainConfig.Posv != nil { return posv.New(chainConfig.Posv, db) } - // Otherwise assume proof-of-work - switch { - case config.PowMode == ethash.ModeFake: - log.Warn("Ethash used in fake mode") - return ethash.NewFaker() - case config.PowMode == ethash.ModeTest: - log.Warn("Ethash used in test mode") - return ethash.NewTester() - case config.PowMode == ethash.ModeShared: - log.Warn("Ethash used in shared mode") - return ethash.NewShared() - default: - engine := ethash.New(ethash.Config{ - CacheDir: ctx.ResolvePath(config.CacheDir), - CachesInMem: config.CachesInMem, - CachesOnDisk: config.CachesOnDisk, - DatasetDir: config.DatasetDir, - DatasetsInMem: config.DatasetsInMem, - DatasetsOnDisk: config.DatasetsOnDisk, - }) - engine.SetThreads(-1) // Disable CPU mining - return engine - } + // Otherwise, return nil + return nil + //// Otherwise assume proof-of-work + //switch { + //case config.PowMode == ethash.ModeFake: + // log.Warn("Ethash used in fake mode") + // return ethash.NewFaker() + //case config.PowMode == ethash.ModeTest: + // log.Warn("Ethash used in test mode") + // return ethash.NewTester() + //case config.PowMode == ethash.ModeShared: + // log.Warn("Ethash used in shared mode") + // return ethash.NewShared() + //default: + // engine := ethash.New(ethash.Config{ + // CacheDir: ctx.ResolvePath(config.CacheDir), + // CachesInMem: config.CachesInMem, + // CachesOnDisk: config.CachesOnDisk, + // DatasetDir: config.DatasetDir, + // DatasetsInMem: config.DatasetsInMem, + // DatasetsOnDisk: config.DatasetsOnDisk, + // }) + // engine.SetThreads(-1) // Disable CPU mining + // return engine + //} } // APIs returns the collection of RPC services the ethereum package offers. diff --git a/eth/handler.go b/eth/handler.go index 322a888ade..df2435b080 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -165,7 +165,11 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne manager.downloader = downloader.New(mode, chaindb, manager.eventMux, blockchain, nil, manager.removePeer) validator := func(header *types.Header) error { - return engine.VerifyHeader(blockchain, header, true) + state, err := blockchain.State() + if err != nil { + return err + } + return engine.VerifyHeader(blockchain, state, header, true) } heighter := func() uint64 { return blockchain.CurrentBlock().NumberU64() diff --git a/light/lightchain.go b/light/lightchain.go index 2784615d35..a59535049d 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -344,7 +344,11 @@ func (self *LightChain) postChainEvents(events []interface{}) { // chain events when necessary. func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { start := time.Now() - if i, err := self.hc.ValidateHeaderChain(chain, checkFreq); err != nil { + state, err := self.State() + if err != nil { + return 0, err + } + if i, err := self.hc.ValidateHeaderChain(chain, state, checkFreq); err != nil { return i, err } diff --git a/miner/worker.go b/miner/worker.go index a5d5167fb4..41103c87af 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -552,7 +552,7 @@ func (self *worker) commitNewWork() { if atomic.LoadInt32(&self.mining) == 1 { header.Coinbase = self.coinbase } - if err := self.engine.Prepare(self.chain, header); err != nil { + if err := self.engine.Prepare(self.chain, self.current.state, header); err != nil { log.Error("Failed to prepare header for new block", "err", err) return } From 5a5e2dbc1a17db237ca002b549c7ce1b8026073b Mon Sep 17 00:00:00 2001 From: Tuna Date: Tue, 8 Jan 2019 16:40:20 +0700 Subject: [PATCH 10/21] remove debug info --- contracts/blockSignerReader.go | 13 ------------ contracts/randomizeReader.go | 21 ------------------- contracts/validatorReader.go | 38 +--------------------------------- 3 files changed, 1 insertion(+), 71 deletions(-) diff --git a/contracts/blockSignerReader.go b/contracts/blockSignerReader.go index f270589d5d..46b72e889a 100644 --- a/contracts/blockSignerReader.go +++ b/contracts/blockSignerReader.go @@ -1,13 +1,7 @@ package contracts import ( - "fmt" - "strings" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - blockSignerContract "github.com/ethereum/go-ethereum/contracts/blocksigner/contract" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" ) @@ -17,13 +11,9 @@ var ( "blockSigners": 0, "blocks": 1, } - ParsedBlockSignerABI, _ = abi.JSON(strings.NewReader(blockSignerContract.BlockSignerABI)) ) func GetSigners(statedb *state.StateDB, block *types.Block) []common.Address { - methodName := "getSigners" - fmt.Printf("---%s---\n", methodName) - start := time.Now() slot := slotBlockSignerMapping["blockSigners"] keys := []common.Hash{} keyArrSlot := getLocMappingAtKey(block.Hash(), slot) @@ -37,10 +27,7 @@ func GetSigners(statedb *state.StateDB, block *types.Block) []common.Address { for _, key := range keys { ret := statedb.GetState(common.HexToAddress(common.BlockSigners), key) rets = append(rets, common.HexToAddress(ret.Hex())) - fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) } - elapsed := time.Since(start) - fmt.Printf("Execution time: %s\n", elapsed) return rets } diff --git a/contracts/randomizeReader.go b/contracts/randomizeReader.go index fd2d4bc3a0..173e82afbb 100644 --- a/contracts/randomizeReader.go +++ b/contracts/randomizeReader.go @@ -1,13 +1,7 @@ package contracts import ( - "fmt" - "strings" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - randomizeContract "github.com/ethereum/go-ethereum/contracts/randomize/contract" "github.com/ethereum/go-ethereum/core/state" ) @@ -16,17 +10,12 @@ var ( "randomSecret": 0, "randomOpening": 1, } - ParsedRandomizeABI, _ = abi.JSON(strings.NewReader(randomizeContract.TomoRandomizeABI)) ) func GetSecret(statedb *state.StateDB, address common.Address) [][32]byte { - start := time.Now() - fmt.Printf("--------GetSecret---------\n") - slot := slotRandomizeMapping["randomSecret"] locSecret := getLocMappingAtKey(address.Hash(), slot) arrLength := statedb.GetState(common.HexToAddress(common.RandomizeSMC), common.BigToHash(locSecret)) - fmt.Printf("Secret length: %v\n", arrLength.Hex()) keys := []common.Hash{} for i := uint64(0); i < arrLength.Big().Uint64(); i++ { key := getLocDynamicArrAtElement(common.BigToHash(locSecret), i, 1) @@ -36,23 +25,13 @@ func GetSecret(statedb *state.StateDB, address common.Address) [][32]byte { for _, key := range keys { ret := statedb.GetState(common.HexToAddress(common.RandomizeSMC), key) rets = append(rets, ret) - fmt.Printf("ret hex: %v - ret byte: %v\n", ret.Hex(), ret.Bytes()) } - elapsed := time.Since(start) - - fmt.Printf("Execution time: %s\n", elapsed) return rets } func GetOpening(statedb *state.StateDB, address common.Address) [32]byte { - start := time.Now() - fmt.Printf("--------GetOpening---------\n") - slot := slotRandomizeMapping["randomOpening"] locOpening := getLocMappingAtKey(address.Hash(), slot) ret := statedb.GetState(common.HexToAddress(common.RandomizeSMC), common.BigToHash(locOpening)) - fmt.Printf("ret hex: %v - ret byte: %v\n", ret.Hex(), ret.Bytes()) - elapsed := time.Since(start) - fmt.Printf("Execution time: %s\n", elapsed) return ret } diff --git a/contracts/validatorReader.go b/contracts/validatorReader.go index e471ae31fd..5311f2f8fe 100644 --- a/contracts/validatorReader.go +++ b/contracts/validatorReader.go @@ -1,20 +1,15 @@ package contracts import ( - "fmt" "math/big" - "strings" - "time" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - validatorContract "github.com/ethereum/go-ethereum/contracts/validator/contract" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/crypto" ) var ( - ParsedValidatorABI, _ = abi.JSON(strings.NewReader(validatorContract.TomoValidatorABI)) slotValidatorMapping = map[string]uint64{ "withdrawsState": 0, "validatorsState": 1, @@ -29,12 +24,10 @@ var ( } ) -func GetCandidates(statedb *state.StateDB, parsed abi.ABI) []common.Address { - start := time.Now() +func GetCandidates(statedb *state.StateDB) []common.Address { slot := slotValidatorMapping["candidates"] slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), slotHash) - fmt.Printf("Candidates length: %v\n", arrLength.Hex()) keys := []common.Hash{} for i := uint64(0); i < arrLength.Big().Uint64(); i++ { key := getLocDynamicArrAtElement(slotHash, i, 1) @@ -44,53 +37,33 @@ func GetCandidates(statedb *state.StateDB, parsed abi.ABI) []common.Address { for _, key := range keys { ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), key) rets = append(rets, common.HexToAddress(ret.Hex())) - fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) } - elapsed := time.Since(start) - fmt.Printf("Execution time: %s\n", elapsed) return rets } func GetCandidateOwner(statedb *state.StateDB, candidate common.Address) common.Address { - start := time.Now() - fmt.Printf("--------GetCandidateOwner---------\n") - slot := slotValidatorMapping["validatorsState"] // validatorsState[_candidate].owner; locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) locCandidateOwner := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(0))) ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locCandidateOwner)) - fmt.Printf("ret: %v\n", common.HexToAddress(ret.Hex()).Hex()) - - elapsed := time.Since(start) - fmt.Printf("Execution time: %s\n", elapsed) return common.HexToAddress(ret.Hex()) } func GetCandidateCap(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) string { - start := time.Now() - slot := slotValidatorMapping["validatorsState"] // validatorsState[_candidate].cap; locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) locCandidateCap := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(1))) ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locCandidateCap)) - fmt.Printf("ret hex: %v\n", ret.Hex()) - - elapsed := time.Since(start) - fmt.Printf("Execution time: %s\n", elapsed) return ret.Hex() } func GetVoters(statedb *state.StateDB, candidate common.Address) []common.Address { - start := time.Now() - fmt.Printf("--------GetVoters---------\n") - //mapping(address => address[]) voters; slot := slotValidatorMapping["voters"] locVoters := getLocMappingAtKey(candidate.Hash(), slot) arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locVoters)) - fmt.Printf("Voters length: %v\n", arrLength.Hex()) keys := []common.Hash{} for i := uint64(0); i < arrLength.Big().Uint64(); i++ { key := getLocDynamicArrAtElement(common.BigToHash(locVoters), i, 1) @@ -100,25 +73,16 @@ func GetVoters(statedb *state.StateDB, candidate common.Address) []common.Addres for _, key := range keys { ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), key) rets = append(rets, common.HexToAddress(ret.Hex())) - fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) } - elapsed := time.Since(start) - fmt.Printf("Execution time: %s\n", elapsed) return rets } func GetVoterCap(state *state.StateDB, candidate, voter common.Address) *big.Int { - //validatorsState[_candidate].voters[_voter] - start := time.Now() - fmt.Printf("--------GetVoterCap---------\n") slot := slotValidatorMapping["validatorsState"] locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) locCandidateVoters := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(2))) retByte := crypto.Keccak256(voter.Hash().Bytes(), common.BigToHash(locCandidateVoters).Bytes()) ret := state.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BytesToHash(retByte)) - fmt.Printf("voter: %v - cap: %v\n", voter.Hex(), ret.Big().String()) - elapsed := time.Since(start) - fmt.Printf("Execution time: %s\n", elapsed) return ret.Big() } From 9a9796a1a218fed48b6b5f4cc64acc46958e0378 Mon Sep 17 00:00:00 2001 From: Tuna Date: Wed, 9 Jan 2019 13:43:46 +0700 Subject: [PATCH 11/21] tmp fix ethash unittests --- cmd/utils/flags.go | 24 ++++++------- consensus/ethash/consensus.go | 18 +++++----- contracts/validator/validator_test.go | 2 +- core/block_validator_test.go | 17 +++++----- core/blockchain_test.go | 6 ++-- eth/backend.go | 49 +++++++++++++-------------- light/lightchain_test.go | 3 +- 7 files changed, 61 insertions(+), 58 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 5aac42b208..d1bff61b65 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -33,7 +33,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/consensus" - //"github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/posv" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -1245,17 +1245,17 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai if config.Posv != nil { engine = posv.New(config.Posv, chainDb) } else { - //engine = ethash.NewFaker() - //if !ctx.GlobalBool(FakePoWFlag.Name) { - // engine = ethash.New(ethash.Config{ - // CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir), - // CachesInMem: eth.DefaultConfig.Ethash.CachesInMem, - // CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk, - // DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir), - // DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem, - // DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, - // }) - //} + engine = ethash.NewFaker() + if !ctx.GlobalBool(FakePoWFlag.Name) { + engine = ethash.New(ethash.Config{ + CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir), + CachesInMem: eth.DefaultConfig.Ethash.CachesInMem, + CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk, + DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir), + DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem, + DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, + }) + } Fatalf("Only support posv consensus") } if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 99eec82211..53b4ce968e 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -66,7 +66,7 @@ func (ethash *Ethash) Author(header *types.Header) (common.Address, error) { // VerifyHeader checks whether a header conforms to the consensus rules of the // stock Ethereum ethash engine. -func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { +func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, seal bool) error { // If we're running a full engine faking, accept any input as valid if ethash.config.PowMode == ModeFullFake { return nil @@ -81,13 +81,13 @@ func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.He return consensus.ErrUnknownAncestor } // Sanity checks passed, do a proper verification - return ethash.verifyHeader(chain, header, parent, false, seal) + return ethash.verifyHeader(chain, state, header, parent, false, seal) } // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers // concurrently. The method returns a quit channel to abort the operations and // a results channel to retrieve the async verifications. -func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { +func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { // If we're running a full engine faking, accept any input as valid if ethash.config.PowMode == ModeFullFake || len(headers) == 0 { abort, results := make(chan struct{}), make(chan error, len(headers)) @@ -113,7 +113,7 @@ func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, headers []*type for i := 0; i < workers; i++ { go func() { for index := range inputs { - errors[index] = ethash.verifyHeaderWorker(chain, headers, seals, index) + errors[index] = ethash.verifyHeaderWorker(chain, state, headers, seals, index) done <- index } }() @@ -149,7 +149,7 @@ func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, headers []*type return abort, errorsOut } -func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error { +func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, seals []bool, index int) error { var parent *types.Header if index == 0 { parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) @@ -162,7 +162,7 @@ func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, headers [] if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil { return nil // known block } - return ethash.verifyHeader(chain, headers[index], parent, false, seals[index]) + return ethash.verifyHeader(chain, state, headers[index], parent, false, seals[index]) } // VerifyUncles verifies that the given block's uncles conform to the consensus @@ -210,7 +210,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { return errDanglingUncle } - if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil { + if err := ethash.verifyHeader(chain, nil, uncle, ancestors[uncle.ParentHash], true, true); err != nil { return err } } @@ -220,7 +220,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo // verifyHeader checks whether a header conforms to the consensus rules of the // stock Ethereum ethash engine. // See YP section 4.3.4. "Block Header Validity" -func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error { +func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, state *state.StateDB, header, parent *types.Header, uncle bool, seal bool) error { // Ensure that the header's extra-data section is of a reasonable size if uint64(len(header.Extra)) > params.MaximumExtraDataSize { return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) @@ -502,7 +502,7 @@ func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Head // Prepare implements consensus.Engine, initializing the difficulty field of a // header to conform to the ethash protocol. The changes are done inline. -func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header) error { +func (ethash *Ethash) Prepare(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error { parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) if parent == nil { return consensus.ErrUnknownAncestor diff --git a/contracts/validator/validator_test.go b/contracts/validator/validator_test.go index f3896db4b8..346066b162 100644 --- a/contracts/validator/validator_test.go +++ b/contracts/validator/validator_test.go @@ -144,7 +144,7 @@ func TestRewardBalance(t *testing.T) { foundationAddr := common.HexToAddress(common.FoudationAddr) totalReward := new(big.Int).SetInt64(15 * 1000) - rewards, err := contracts.GetRewardBalancesRate(foundationAddr, acc3Addr, totalReward, baseValidator) + rewards, err := contracts.GetRewardBalancesRate(foundationAddr, nil, acc3Addr, totalReward) if err != nil { t.Error("Fail to get reward balances rate.", err) } diff --git a/core/block_validator_test.go b/core/block_validator_test.go index e334b3c3cd..d085effdc8 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -48,13 +48,13 @@ func TestHeaderVerification(t *testing.T) { for i := 0; i < len(blocks); i++ { for j, valid := range []bool{true, false} { var results <-chan error - + state, _ := chain.State() if valid { engine := ethash.NewFaker() - _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}) + _, results = engine.VerifyHeaders(chain, state, []*types.Header{headers[i]}, []bool{true}) } else { engine := ethash.NewFakeFailer(headers[i].Number.Uint64()) - _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}) + _, results = engine.VerifyHeaders(chain, state, []*types.Header{headers[i]}, []bool{true}) } // Wait for the verification result select { @@ -104,14 +104,15 @@ 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) + state, _ := chain.State() + _, results = chain.engine.VerifyHeaders(chain, state, headers, seals) chain.Stop() } else { chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}) - _, results = chain.engine.VerifyHeaders(chain, headers, seals) + state, _ := chain.State() + _, results = chain.engine.VerifyHeaders(chain, state, headers, seals) chain.Stop() } // Wait for all the verification results @@ -175,8 +176,8 @@ 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) + state, _ := chain.State() + abort, results := chain.engine.VerifyHeaders(chain, state, headers, seals) close(abort) // Deplete the results channel diff --git a/core/blockchain_test.go b/core/blockchain_test.go index b752b9ef8d..46203a4f37 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -103,7 +103,8 @@ func printChain(bc *BlockChain) { func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { for _, block := range chain { // Try and process the block - err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) + st, _ := blockchain.State() + err := blockchain.engine.VerifyHeader(blockchain, st, block.Header(), true) if err == nil { err = blockchain.validator.ValidateBody(block) } @@ -141,7 +142,8 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { for _, header := range chain { // Try and validate the header - if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { + state, _ := blockchain.State() + if err := blockchain.engine.VerifyHeader(blockchain, state, header, false); err != nil { return err } // Manually insert the header into the database, but don't reorganise (allows subsequent testing) diff --git a/eth/backend.go b/eth/backend.go index ad58f0677c..dae51e9582 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -393,31 +393,30 @@ func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chai if chainConfig.Posv != nil { return posv.New(chainConfig.Posv, db) } - // Otherwise, return nil - return nil - //// Otherwise assume proof-of-work - //switch { - //case config.PowMode == ethash.ModeFake: - // log.Warn("Ethash used in fake mode") - // return ethash.NewFaker() - //case config.PowMode == ethash.ModeTest: - // log.Warn("Ethash used in test mode") - // return ethash.NewTester() - //case config.PowMode == ethash.ModeShared: - // log.Warn("Ethash used in shared mode") - // return ethash.NewShared() - //default: - // engine := ethash.New(ethash.Config{ - // CacheDir: ctx.ResolvePath(config.CacheDir), - // CachesInMem: config.CachesInMem, - // CachesOnDisk: config.CachesOnDisk, - // DatasetDir: config.DatasetDir, - // DatasetsInMem: config.DatasetsInMem, - // DatasetsOnDisk: config.DatasetsOnDisk, - // }) - // engine.SetThreads(-1) // Disable CPU mining - // return engine - //} + + // Otherwise assume proof-of-work + switch { + case config.PowMode == ethash.ModeFake: + log.Warn("Ethash used in fake mode") + return ethash.NewFaker() + case config.PowMode == ethash.ModeTest: + log.Warn("Ethash used in test mode") + return ethash.NewTester() + case config.PowMode == ethash.ModeShared: + log.Warn("Ethash used in shared mode") + return ethash.NewShared() + default: + engine := ethash.New(ethash.Config{ + CacheDir: ctx.ResolvePath(config.CacheDir), + CachesInMem: config.CachesInMem, + CachesOnDisk: config.CachesOnDisk, + DatasetDir: config.DatasetDir, + DatasetsInMem: config.DatasetsInMem, + DatasetsOnDisk: config.DatasetsOnDisk, + }) + engine.SetThreads(-1) // Disable CPU mining + return engine + } } // APIs returns the collection of RPC services the ethereum package offers. diff --git a/light/lightchain_test.go b/light/lightchain_test.go index 0af7551d41..20e9556b1b 100644 --- a/light/lightchain_test.go +++ b/light/lightchain_test.go @@ -117,7 +117,8 @@ func testFork(t *testing.T, LightChain *LightChain, i, n int, comparator func(td func testHeaderChainImport(chain []*types.Header, lightchain *LightChain) error { for _, header := range chain { // Try and validate the header - if err := lightchain.engine.VerifyHeader(lightchain.hc, header, true); err != nil { + state, _ := lightchain.State() + if err := lightchain.engine.VerifyHeader(lightchain.hc, state, header, true); err != nil { return err } // Manually insert the header into the database, but don't reorganize (allows subsequent testing) From 804debede41a5aaaae65f4f36ced1044d37cbba4 Mon Sep 17 00:00:00 2001 From: Tuna Date: Wed, 9 Jan 2019 15:43:12 +0700 Subject: [PATCH 12/21] fix nil exception --- consensus/posv/posv.go | 2 +- miner/worker.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index b86028cce0..c92371c846 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -774,7 +774,7 @@ func (c *Posv) Prepare(chain consensus.ChainReader, state *state.StateDB, header } header.Extra = header.Extra[:extraVanity] masternodes := snap.GetSigners() - if number > 0 && number%c.config.Epoch == 0 { + if number >= c.config.Epoch && number%c.config.Epoch == 0 { if c.HookPenalty != nil { penMasternodes, err := c.HookPenalty(state, chain, number) if err != nil { diff --git a/miner/worker.go b/miner/worker.go index 41103c87af..809a132777 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -552,7 +552,11 @@ func (self *worker) commitNewWork() { if atomic.LoadInt32(&self.mining) == 1 { header.Coinbase = self.coinbase } - if err := self.engine.Prepare(self.chain, self.current.state, header); err != nil { + state := &state.StateDB{} + if self.current != nil { + state = self.current.state + } + if err := self.engine.Prepare(self.chain, state, header); err != nil { log.Error("Failed to prepare header for new block", "err", err) return } From 4455673db45271c0e79e35f8f85388849b52f972 Mon Sep 17 00:00:00 2001 From: Tuna Date: Thu, 10 Jan 2019 11:42:23 +0700 Subject: [PATCH 13/21] revert HookValidator, HookPenalty, HookVerifyMNs; only keep HookReward go the new way --- consensus/posv/posv.go | 14 +++++++------- contracts/utils.go | 38 +++++++++++++++++++++++++++++++++++--- eth/backend.go | 37 ++++++++++++++++++++++++++----------- 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index c92371c846..912eb146d8 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -225,9 +225,9 @@ type Posv struct { lock sync.RWMutex // Protects the signer fields HookReward func(state *state.StateDB, chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) - HookPenalty func(state *state.StateDB, chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) - HookValidator func(state *state.StateDB, header *types.Header, signers []common.Address) ([]byte, error) - HookVerifyMNs func(state *state.StateDB, header *types.Header, signers []common.Address) error + HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) + HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) + HookVerifyMNs func(header *types.Header, signers []common.Address) error } // New creates a PoSV proof-of-stake-voting consensus engine with the initial @@ -392,7 +392,7 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, state *state.S if number%c.config.Epoch == 0 { penPenalties := []common.Address{} if c.HookPenalty != nil { - penPenalties, err = c.HookPenalty(state, chain, number) + penPenalties, err = c.HookPenalty(chain, number) if err != nil { return err } @@ -417,7 +417,7 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, state *state.S return errInvalidCheckpointSigners } if c.HookVerifyMNs != nil { - err := c.HookVerifyMNs(state, header, signers) + err := c.HookVerifyMNs(header, signers) if err != nil { return err } @@ -776,7 +776,7 @@ func (c *Posv) Prepare(chain consensus.ChainReader, state *state.StateDB, header masternodes := snap.GetSigners() if number >= c.config.Epoch && number%c.config.Epoch == 0 { if c.HookPenalty != nil { - penMasternodes, err := c.HookPenalty(state, chain, number) + penMasternodes, err := c.HookPenalty(chain, number) if err != nil { return err } @@ -799,7 +799,7 @@ func (c *Posv) Prepare(chain consensus.ChainReader, state *state.StateDB, header header.Extra = append(header.Extra, masternode[:]...) } if c.HookValidator != nil { - validators, err := c.HookValidator(state, header, masternodes) + validators, err := c.HookValidator(header, masternodes) if err != nil { return err } diff --git a/contracts/utils.go b/contracts/utils.go index e04418df5e..00f8bac0ac 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -41,6 +41,9 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/contracts/blocksigner/contract" + randomizeContract "github.com/ethereum/go-ethereum/contracts/randomize/contract" ) const ( @@ -199,10 +202,39 @@ func GetSignersFromContract(state *state.StateDB, block *types.Block) ([]common. return GetSigners(state, block), nil } +// Get signers signed for blockNumber from blockSigner contract. +func GetSignersFromContract1(addrBlockSigner common.Address, client bind.ContractBackend, blockHash common.Hash) ([]common.Address, error) { + blockSigner, err := contract.NewBlockSigner(addrBlockSigner, client) + if err != nil { + log.Error("Fail get instance of blockSigner", "error", err) + return nil, err + } + opts := new(bind.CallOpts) + addrs, err := blockSigner.GetSigners(opts, blockHash) + if err != nil { + log.Error("Fail get block signers", "error", err) + return nil, err + } + + return addrs, nil +} + // Get random from randomize contract. -func GetRandomizeFromContract(state *state.StateDB, addrMasternode common.Address) (int64, error) { - secrets := GetSecret(state, addrMasternode) - opening := GetOpening(state, addrMasternode) +func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common.Address) (int64, error) { + randomize, err := randomizeContract.NewTomoRandomize(common.HexToAddress(common.RandomizeSMC), client) + if err != nil { + log.Error("Fail to get instance of randomize", "error", err) + } + opts := new(bind.CallOpts) + secrets, err := randomize.GetSecret(opts, addrMasternode) + if err != nil { + log.Error("Fail get secrets from randomize", "error", err) + } + opening, err := randomize.GetOpening(opts, addrMasternode) + if err != nil { + log.Error("Fail get opening from randomize", "error", err) + } + return DecryptRandomizeFromSecretsAndOpening(secrets, opening) } diff --git a/eth/backend.go b/eth/backend.go index dae51e9582..f5a8c9b309 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -230,9 +230,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { eth.protocolManager.fetcher.SetAppendM2HeaderHook(appendM2HeaderHook) // Hook prepares validators M2 for the current epoch at checkpoint block - c.HookValidator = func(state *state.StateDB, header *types.Header, signers []common.Address) ([]byte, error) { + c.HookValidator = func(header *types.Header, signers []common.Address) ([]byte, error) { start := time.Now() - validators, err := GetValidators(state, signers) + validators, err := GetValidators(eth.blockchain, signers) if err != nil { return []byte{}, err } @@ -242,20 +242,23 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } // Hook scans for bad masternodes and decide to penalty them - c.HookPenalty = func(state *state.StateDB, chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) { + c.HookPenalty = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) { + client, err := eth.blockchain.GetClient() + if err != nil { + return nil, err + } prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch if prevEpoc >= 0 { start := time.Now() prevHeader := chain.GetHeaderByNumber(prevEpoc) penSigners := c.GetMasternodes(chain, prevHeader) if len(penSigners) > 0 { + blockSignerAddr := common.HexToAddress(common.BlockSigners) // Loop for each block to check missing sign. for i := prevEpoc; i < blockNumberEpoc; i++ { - bHeader := chain.GetHeaderByNumber(i) - bHash := bHeader.Hash() - block := chain.GetBlock(bHash, i) + blockHeader := chain.GetHeaderByNumber(i) if len(penSigners) > 0 { - signedMasternodes, err := contracts.GetSignersFromContract(state, block) + signedMasternodes, err := contracts.GetSignersFromContract1(blockSignerAddr, client, blockHeader.Hash()) if err != nil { return nil, err } @@ -327,11 +330,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } // Hook verifies masternodes set - c.HookVerifyMNs = func(state *state.StateDB, header *types.Header, signers []common.Address) error { + c.HookVerifyMNs = func(header *types.Header, signers []common.Address) error { number := header.Number.Int64() if number > 0 && number%common.EpocBlockRandomize == 0 { start := time.Now() - validators, err := GetValidators(state, signers) + validators, err := GetValidators(eth.blockchain, signers) log.Debug("Time Calculated HookVerifyMNs ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) if err != nil { return err @@ -342,6 +345,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } return nil } + eth.txPool.IsMasterNode = func(address common.Address) bool { currentHeader := eth.blockchain.CurrentHeader() snap, err := c.GetSnapshot(eth.blockchain, currentHeader) @@ -631,14 +635,25 @@ func (s *Ethereum) Stop() error { return nil } -func GetValidators(state *state.StateDB, masternodes []common.Address) ([]byte, error) { +func GetValidators(bc *core.BlockChain, masternodes []common.Address) ([]byte, error) { + if bc.Config().Posv == nil { + return nil, core.ErrNotPoSV + } + client, err := bc.GetClient() + if err != nil { + return nil, err + } // Check m2 exists on chaindb. // Get secrets and opening at epoc block checkpoint. + var candidates []int64 + if err != nil { + return nil, err + } lenSigners := int64(len(masternodes)) if lenSigners > 0 { for _, addr := range masternodes { - random, err := contracts.GetRandomizeFromContract(state, addr) + random, err := contracts.GetRandomizeFromContract(client, addr) if err != nil { return nil, err } From 34179cae22224faa7a71cc4a37796e19b3a7cf06 Mon Sep 17 00:00:00 2001 From: Tuna Date: Thu, 10 Jan 2019 17:29:18 +0700 Subject: [PATCH 14/21] get state on chain at HookReward --- consensus/posv/posv.go | 4 ++-- eth/backend.go | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index 912eb146d8..e0d3d1eca5 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -224,7 +224,7 @@ type Posv struct { signFn clique.SignerFn // Signer function to authorize hashes with lock sync.RWMutex // Protects the signer fields - HookReward func(state *state.StateDB, chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) + HookReward func(chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) HookVerifyMNs func(header *types.Header, signers []common.Address) error @@ -850,7 +850,7 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state rCheckpoint := chain.Config().Posv.RewardCheckpoint if c.HookReward != nil && number%rCheckpoint == 0 { - err, rewards := c.HookReward(state, chain, header) + err, rewards := c.HookReward(chain, header) if err != nil { return nil, err } diff --git a/eth/backend.go b/eth/backend.go index f5a8c9b309..9a6fe46806 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -36,7 +36,7 @@ import ( "github.com/ethereum/go-ethereum/contracts" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/state" + //"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/downloader" @@ -285,7 +285,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } // Hook calculates reward for masternodes - c.HookReward = func(state *state.StateDB, chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) { + c.HookReward = func(chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) { + state, err := eth.blockchain.State() + if state == nil || err != nil { + log.Crit("Can't get state", "block number", header.Number.Uint64(), "err", err) + } number := header.Number.Uint64() rCheckpoint := chain.Config().Posv.RewardCheckpoint foundationWalletAddr := chain.Config().Posv.FoudationWalletAddr From ae6eb505b7b9f6c8bec46b650f209b2fb87427e6 Mon Sep 17 00:00:00 2001 From: Tuna Date: Fri, 11 Jan 2019 09:35:18 +0700 Subject: [PATCH 15/21] return correct state at HookReward --- consensus/posv/posv.go | 4 ++-- eth/backend.go | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index e0d3d1eca5..39781d73b7 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -224,7 +224,7 @@ type Posv struct { signFn clique.SignerFn // Signer function to authorize hashes with lock sync.RWMutex // Protects the signer fields - HookReward func(chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) + HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) HookVerifyMNs func(header *types.Header, signers []common.Address) error @@ -850,7 +850,7 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state rCheckpoint := chain.Config().Posv.RewardCheckpoint if c.HookReward != nil && number%rCheckpoint == 0 { - err, rewards := c.HookReward(chain, header) + err, rewards := c.HookReward(chain, state, header) if err != nil { return nil, err } diff --git a/eth/backend.go b/eth/backend.go index 9a6fe46806..f3eef4ddf0 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -52,6 +52,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/core/state" ) type LesServer interface { @@ -285,10 +286,10 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } // Hook calculates reward for masternodes - c.HookReward = func(chain consensus.ChainReader, header *types.Header) (error, map[string]interface{}) { - state, err := eth.blockchain.State() - if state == nil || err != nil { - log.Crit("Can't get state", "block number", header.Number.Uint64(), "err", err) + c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) { + canonicalState, err := eth.blockchain.State() + if canonicalState == nil || err != nil { + log.Crit("Can't get state at head of canonical chain", "head number", header.Number.Uint64(), "err", err) } number := header.Number.Uint64() rCheckpoint := chain.Config().Posv.RewardCheckpoint @@ -306,7 +307,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { chainReward = rewardInflation(chainReward, number, common.BlocksPerYear) totalSigner := new(uint64) - signers, err := contracts.GetRewardForCheckpoint(chain, number, rCheckpoint, totalSigner, state) + signers, err := contracts.GetRewardForCheckpoint(chain, number, rCheckpoint, totalSigner, canonicalState) log.Debug("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) if err != nil { log.Crit("Fail to get signers for reward checkpoint", "error", err) From 9d118a4620a15a24fd00b9ef06f2856a044b8aa8 Mon Sep 17 00:00:00 2001 From: Tuna Date: Fri, 11 Jan 2019 17:42:33 +0700 Subject: [PATCH 16/21] use correct state when changing balances --- contracts/test.go | 281 +++++++++++++++++++++++++++++++++++++++++++++ contracts/utils.go | 6 +- eth/backend.go | 7 +- 3 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 contracts/test.go diff --git a/contracts/test.go b/contracts/test.go new file mode 100644 index 0000000000..a71056455e --- /dev/null +++ b/contracts/test.go @@ -0,0 +1,281 @@ +package contracts +// +//import ( +// "fmt" +// "math/big" +// "time" +// +// "github.com/ethereum/go-ethereum/common" +// "github.com/ethereum/go-ethereum/core" +// "github.com/ethereum/go-ethereum/core/state" +// "github.com/ethereum/go-ethereum/crypto" +// "github.com/ethereum/go-ethereum/ethdb" +// "github.com/ethereum/go-ethereum/core/types" +//) +// +//var ( +// slotValidatorMapping = map[string]uint64{ +// "withdrawsState": 0, +// "validatorsState": 1, +// "voters": 2, +// "candidates": 3, +// "candidateCount": 4, +// "minCandidateCap": 5, +// "minVoterCap": 6, +// "maxValidatorNumber": 7, +// "candidateWithdrawDelay": 8, +// "voterWithdrawDelay": 9, +// } +// slotBlockSignerMapping = map[string]uint64{ +// "blockSigners": 0, +// "blocks": 1, +// } +// slotRandomizeMapping = map[string]uint64{ +// "randomSecret": 0, +// "randomOpening": 1, +// } +// datadir = "/mnt/sgp1_tuna_chaindata3/data/tomo/chaindata" +// candidate = "0xd6fa3e7a89bf8c84f0ccd204a15c0d259daf2091" +//) +// +//func main() { +// //Init +// chaindb, err := ethdb.NewLDBDatabase(datadir, 0, 0) +// if err != nil || chaindb == nil { +// fmt.Printf("Can't get chaindb: %v", err) +// return +// } +// headHash := core.GetHeadBlockHash(chaindb) +// blockNumber := core.GetBlockNumber(chaindb, headHash) +// block := core.GetBlock(chaindb, headHash, blockNumber) +// if block == nil { +// fmt.Println("Can't get head block") +// return +// } +// database := state.NewDatabase(chaindb) +// headerRootHash := block.Header().Root +// headHeaderHash := core.GetHeadHeaderHash(chaindb) +// statedb, _ := state.New(headHeaderHash, database) +// if statedb == nil { +// headHeaderHash = headerRootHash +// } +// candidateAddress := common.HexToAddress(candidate) +// fmt.Printf("Block head :%d, header root:%v\n", blockNumber, headerRootHash.Hex()) +// statedb, _ = state.New(headHeaderHash, database) +// if statedb == nil { +// fmt.Println("Can't get state db") +// return +// } +// +// //GetCandidates +// _ = GetCandidates(statedb) +// +// //GetCandidateOwner +// _ = GetCandidateOwner(statedb, candidateAddress) +// +// //GetCandidateCap +// _ = GetCandidateCap(statedb, candidateAddress) +// +// //GetVoters +// voters := GetVoters(statedb, candidateAddress) +// +// start := time.Now() +// fmt.Printf("--------GetVoterCap---------\n") +// for _, voter := range voters { +// //GetVoterCap +// _ = GetVoterCap(statedb, candidateAddress, voter) +// } +// elapsed := time.Since(start) +// fmt.Printf("Execution time: %s\n", elapsed) +// +// //GetSigners +// blockInput := core.GetBlock(chaindb, common.HexToHash("0x632f2403ea19697082d794900275632eb3373f7a9943b1407461995bbbc2816a"), uint64(1800)) +// _ = GetSigners(statedb, blockInput) +// +// //GetOpening +// _ = GetOpening(statedb, candidateAddress) +// //GetSecret +// _ = GetSecret(statedb, candidateAddress) +//} +// +//func GetCandidates(statedb *state.StateDB) []common.Address { +// start := time.Now() +// fmt.Printf("--------GetCandidates---------\n") +// +// slot := slotValidatorMapping["candidates"] +// slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) +// arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), slotHash) +// fmt.Printf("Candidates length: %v\n", arrLength.Hex()) +// keys := []common.Hash{} +// for i := uint64(0); i < arrLength.Big().Uint64(); i++ { +// key := getLocDynamicArrAtElement(slotHash, i, 1) +// keys = append(keys, key) +// } +// rets := []common.Address{} +// for _, key := range keys { +// ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), key) +// rets = append(rets, common.HexToAddress(ret.Hex())) +// fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) +// } +// elapsed := time.Since(start) +// fmt.Printf("Execution time: %s\n", elapsed) +// return rets +//} +// +//func GetCandidateOwner(statedb *state.StateDB, candidate common.Address) common.Address { +// start := time.Now() +// fmt.Printf("--------GetCandidateOwner---------\n") +// +// slot := slotValidatorMapping["validatorsState"] +// // validatorsState[_candidate].owner; +// locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) +// locCandidateOwner := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(0))) +// ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locCandidateOwner)) +// fmt.Printf("ret: %v\n", common.HexToAddress(ret.Hex()).Hex()) +// +// elapsed := time.Since(start) +// fmt.Printf("Execution time: %s\n", elapsed) +// return common.HexToAddress(ret.Hex()) +//} +// +//func GetCandidateCap(statedb *state.StateDB, candidate common.Address) string { +// start := time.Now() +// fmt.Printf("--------GetCandidateCap---------\n") +// +// slot := slotValidatorMapping["validatorsState"] +// // validatorsState[_candidate].cap; +// locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) +// locCandidateCap := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(1))) +// ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locCandidateCap)) +// fmt.Printf("cap: %v\n", ret.Big().String()) +// +// elapsed := time.Since(start) +// fmt.Printf("Execution time: %s\n", elapsed) +// return ret.Hex() +//} +// +//func GetVoterCap(state *state.StateDB, candidate, voter common.Address) *big.Int { +// //validatorsState[_candidate].voters[_voter] +// slot := slotValidatorMapping["validatorsState"] +// locValidatorsState := getLocMappingAtKey(candidate.Hash(), slot) +// locCandidateVoters := locValidatorsState.Add(locValidatorsState, new(big.Int).SetUint64(uint64(2))) +// retByte := crypto.Keccak256(voter.Hash().Bytes(), common.BigToHash(locCandidateVoters).Bytes()) +// ret := state.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BytesToHash(retByte)) +// fmt.Printf("voter: %v - cap: %v\n", voter.Hex(), ret.Big().String()) +// return ret.Big() +//} +// +//func GetVoters(statedb *state.StateDB, candidate common.Address) []common.Address { +// start := time.Now() +// fmt.Printf("--------GetVoters---------\n") +// +// //mapping(address => address[]) voters; +// slot := slotValidatorMapping["voters"] +// locVoters := getLocMappingAtKey(candidate.Hash(), slot) +// arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locVoters)) +// fmt.Printf("Voters length: %v\n", arrLength.Hex()) +// keys := []common.Hash{} +// for i := uint64(0); i < arrLength.Big().Uint64(); i++ { +// key := getLocDynamicArrAtElement(common.BigToHash(locVoters), i, 1) +// keys = append(keys, key) +// } +// rets := []common.Address{} +// for _, key := range keys { +// ret := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), key) +// rets = append(rets, common.HexToAddress(ret.Hex())) +// fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) +// } +// +// elapsed := time.Since(start) +// fmt.Printf("Execution time: %s\n", elapsed) +// return rets +//} +// +//func GetSigners(statedb *state.StateDB, block *types.Block) []common.Address { +// methodName := "getSigners" +// fmt.Printf("---%s---\n", methodName) +// start := time.Now() +// slot := slotBlockSignerMapping["blockSigners"] +// keys := []common.Hash{} +// keyArrSlot := getLocMappingAtKey(block.Hash(), slot) +// arrSlot := statedb.GetState(common.HexToAddress(common.BlockSigners), common.BigToHash(keyArrSlot)) +// arrLength := arrSlot.Big().Uint64() +// for i := uint64(0); i < arrLength; i++ { +// key := getLocDynamicArrAtElement(common.BigToHash(keyArrSlot), i, 1) +// keys = append(keys, key) +// } +// rets := []common.Address{} +// for _, key := range keys { +// ret := statedb.GetState(common.HexToAddress(common.BlockSigners), key) +// rets = append(rets, common.HexToAddress(ret.Hex())) +// fmt.Printf("%v\n", common.HexToAddress(ret.Hex()).Hex()) +// } +// +// elapsed := time.Since(start) +// fmt.Printf("Execution time: %s\n", elapsed) +// return rets +//} +// +//func GetSecret(statedb *state.StateDB, address common.Address) [][32]byte { +// start := time.Now() +// fmt.Printf("--------GetSecret---------\n") +// +// slot := slotRandomizeMapping["randomSecret"] +// locSecret := getLocMappingAtKey(address.Hash(), slot) +// arrLength := statedb.GetState(common.HexToAddress(common.RandomizeSMC), common.BigToHash(locSecret)) +// fmt.Printf("Secret length: %v\n", arrLength.Hex()) +// keys := []common.Hash{} +// for i := uint64(0); i < arrLength.Big().Uint64(); i++ { +// key := getLocDynamicArrAtElement(common.BigToHash(locSecret), i, 1) +// keys = append(keys, key) +// } +// rets := [][32]byte{} +// for _, key := range keys { +// ret := statedb.GetState(common.HexToAddress(common.RandomizeSMC), key) +// rets = append(rets, ret) +// fmt.Printf("ret hex: %v - ret byte: %v\n", ret.Hex(), ret.Bytes()) +// } +// elapsed := time.Since(start) +// +// fmt.Printf("Execution time: %s\n", elapsed) +// return rets +//} +// +//func GetOpening(statedb *state.StateDB, address common.Address) [32]byte { +// start := time.Now() +// fmt.Printf("--------GetOpening---------\n") +// +// slot := slotRandomizeMapping["randomOpening"] +// locOpening := getLocMappingAtKey(address.Hash(), slot) +// ret := statedb.GetState(common.HexToAddress(common.RandomizeSMC), common.BigToHash(locOpening)) +// fmt.Printf("ret hex: %v - ret byte: %v\n", ret.Hex(), ret.Bytes()) +// elapsed := time.Since(start) +// fmt.Printf("Execution time: %s\n", elapsed) +// return ret +//} +// +// +////////////////////////////////////// +///////////// Common lib ///////////// +////////////////////////////////////// +// +//func getLocMappingAtKey(key common.Hash, slot uint64) *big.Int { +// slotHash := common.BigToHash(new(big.Int).SetUint64(slot)) +// retByte := crypto.Keccak256(key.Bytes(), slotHash.Bytes()) +// ret := new(big.Int) +// ret.SetBytes(retByte) +// return ret +//} +// +//func getLocDynamicArrAtElement(slotHash common.Hash, index uint64, elementSize uint64) common.Hash { +// slotKecBig := crypto.Keccak256Hash(slotHash.Bytes()).Big() +// //arrBig = slotKecBig + index * elementSize +// arrBig := slotKecBig.Add(slotKecBig, new(big.Int).SetUint64(index*elementSize)) +// return common.BigToHash(arrBig) +//} +// +//func getLocFixedArrAtElement(slot uint64, index uint64, elementSize uint64) common.Hash { +// slotBig := new(big.Int).SetUint64(slot) +// arrBig := slotBig.Add(slotBig, new(big.Int).SetUint64(index*elementSize)) +// return common.BigToHash(arrBig) +//} diff --git a/contracts/utils.go b/contracts/utils.go index 00f8bac0ac..36bddadce2 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -394,13 +394,9 @@ func CalculateRewardForHolders(foundationWalletAddr common.Address, state *state if err != nil { return err, nil } - if len(rewards) > 0 { - for holder, reward := range rewards { - state.AddBalance(holder, reward) - } - } return nil, rewards } + func GetRewardBalancesRate(foundationWalletAddr common.Address, state *state.StateDB, masterAddr common.Address, totalReward *big.Int) (map[common.Address]*big.Int, error) { owner := GetCandidatesOwnerBySigner(state, masterAddr) balances := make(map[common.Address]*big.Int) diff --git a/eth/backend.go b/eth/backend.go index f3eef4ddf0..da2ce09408 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -321,10 +321,15 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { voterResults := make(map[common.Address]interface{}) if len(signers) > 0 { for signer, calcReward := range rewardSigners { - err, rewards := contracts.CalculateRewardForHolders(foundationWalletAddr, state, signer, calcReward) + err, rewards := contracts.CalculateRewardForHolders(foundationWalletAddr, canonicalState, signer, calcReward) if err != nil { log.Crit("Fail to calculate reward for holders.", "error", err) } + if len(rewards) > 0 { + for holder, reward := range rewards { + state.AddBalance(holder, reward) + } + } voterResults[signer] = rewards } } From 9e6bc884da6f845c2a115f09bbeabc7e87cac734 Mon Sep 17 00:00:00 2001 From: Tuna Date: Sat, 12 Jan 2019 10:19:52 +0700 Subject: [PATCH 17/21] HookPenalty goes the new way --- eth/backend.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index da2ce09408..6a34d2bb5a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -244,9 +244,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { // Hook scans for bad masternodes and decide to penalty them c.HookPenalty = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) { - client, err := eth.blockchain.GetClient() - if err != nil { - return nil, err + canonicalState, err := eth.blockchain.State() + if canonicalState == nil || err != nil { + log.Crit("Can't get state at head of canonical chain", "head number", eth.blockchain.CurrentHeader().Number.Uint64(), "err", err) } prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch if prevEpoc >= 0 { @@ -254,12 +254,13 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { prevHeader := chain.GetHeaderByNumber(prevEpoc) penSigners := c.GetMasternodes(chain, prevHeader) if len(penSigners) > 0 { - blockSignerAddr := common.HexToAddress(common.BlockSigners) // Loop for each block to check missing sign. for i := prevEpoc; i < blockNumberEpoc; i++ { - blockHeader := chain.GetHeaderByNumber(i) + bheader := chain.GetHeaderByNumber(i) + bhash := bheader.Hash() + block := chain.GetBlock(bhash, i) if len(penSigners) > 0 { - signedMasternodes, err := contracts.GetSignersFromContract1(blockSignerAddr, client, blockHeader.Hash()) + signedMasternodes, err := contracts.GetSignersFromContract(canonicalState, block) if err != nil { return nil, err } From 337b7c64ee3ccd1f8a0c18440609751b2df0f559 Mon Sep 17 00:00:00 2001 From: Tuna Date: Sat, 12 Jan 2019 13:08:01 +0700 Subject: [PATCH 18/21] remove state at verifyHeader, prepare --- consensus/consensus.go | 6 +++--- consensus/ethash/consensus.go | 18 +++++++++--------- consensus/posv/posv.go | 22 +++++++++++----------- core/blockchain.go | 12 ++---------- core/headerchain.go | 2 +- eth/api_tracer.go | 6 +----- eth/handler.go | 6 +----- miner/worker.go | 7 ++----- 8 files changed, 30 insertions(+), 49 deletions(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index 8d992b5dee..b02afa63c4 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -58,13 +58,13 @@ type Engine interface { // VerifyHeader checks whether a header conforms to the consensus rules of a // given engine. Verifying the seal may be done optionally here, or explicitly // via the VerifySeal method. - VerifyHeader(chain ChainReader, state *state.StateDB, header *types.Header, fullVerify bool) error + VerifyHeader(chain ChainReader, header *types.Header, fullVerify bool) error // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers // concurrently. The method returns a quit channel to abort the operations and // a results channel to retrieve the async verifications (the order is that of // the input slice). - VerifyHeaders(chain ChainReader, state *state.StateDB, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) + VerifyHeaders(chain ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) // VerifyUncles verifies that the given block's uncles conform to the consensus // rules of a given engine. @@ -76,7 +76,7 @@ type Engine interface { // Prepare initializes the consensus fields of a block header according to the // rules of a particular engine. The changes are executed inline. - Prepare(chain ChainReader, state *state.StateDB, header *types.Header) error + Prepare(chain ChainReader, header *types.Header) error // Finalize runs any post-transaction state modifications (e.g. block rewards) // and assembles the final block. diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 53b4ce968e..99eec82211 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -66,7 +66,7 @@ func (ethash *Ethash) Author(header *types.Header) (common.Address, error) { // VerifyHeader checks whether a header conforms to the consensus rules of the // stock Ethereum ethash engine. -func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, seal bool) error { +func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { // If we're running a full engine faking, accept any input as valid if ethash.config.PowMode == ModeFullFake { return nil @@ -81,13 +81,13 @@ func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, state *state.Sta return consensus.ErrUnknownAncestor } // Sanity checks passed, do a proper verification - return ethash.verifyHeader(chain, state, header, parent, false, seal) + return ethash.verifyHeader(chain, header, parent, false, seal) } // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers // concurrently. The method returns a quit channel to abort the operations and // a results channel to retrieve the async verifications. -func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { +func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { // If we're running a full engine faking, accept any input as valid if ethash.config.PowMode == ModeFullFake || len(headers) == 0 { abort, results := make(chan struct{}), make(chan error, len(headers)) @@ -113,7 +113,7 @@ func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, state *state.St for i := 0; i < workers; i++ { go func() { for index := range inputs { - errors[index] = ethash.verifyHeaderWorker(chain, state, headers, seals, index) + errors[index] = ethash.verifyHeaderWorker(chain, headers, seals, index) done <- index } }() @@ -149,7 +149,7 @@ func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, state *state.St return abort, errorsOut } -func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, seals []bool, index int) error { +func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error { var parent *types.Header if index == 0 { parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) @@ -162,7 +162,7 @@ func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, state *sta if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil { return nil // known block } - return ethash.verifyHeader(chain, state, headers[index], parent, false, seals[index]) + return ethash.verifyHeader(chain, headers[index], parent, false, seals[index]) } // VerifyUncles verifies that the given block's uncles conform to the consensus @@ -210,7 +210,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { return errDanglingUncle } - if err := ethash.verifyHeader(chain, nil, uncle, ancestors[uncle.ParentHash], true, true); err != nil { + if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil { return err } } @@ -220,7 +220,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo // verifyHeader checks whether a header conforms to the consensus rules of the // stock Ethereum ethash engine. // See YP section 4.3.4. "Block Header Validity" -func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, state *state.StateDB, header, parent *types.Header, uncle bool, seal bool) error { +func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error { // Ensure that the header's extra-data section is of a reasonable size if uint64(len(header.Extra)) > params.MaximumExtraDataSize { return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) @@ -502,7 +502,7 @@ func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Head // Prepare implements consensus.Engine, initializing the difficulty field of a // header to conform to the ethash protocol. The changes are done inline. -func (ethash *Ethash) Prepare(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error { +func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header) error { parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) if parent == nil { return consensus.ErrUnknownAncestor diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index a27e1b3dd8..153c026b26 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -265,20 +265,20 @@ func (c *Posv) Author(header *types.Header) (common.Address, error) { } // VerifyHeader checks whether a header conforms to the consensus rules. -func (c *Posv) VerifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, fullVerify bool) error { - return c.verifyHeaderWithCache(chain, state, header, nil, fullVerify) +func (c *Posv) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error { + return c.verifyHeaderWithCache(chain, header, nil, fullVerify) } // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The // method returns a quit channel to abort the operations and a results channel to // retrieve the async verifications (the order is that of the input slice). -func (c *Posv) VerifyHeaders(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) { +func (c *Posv) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) { abort := make(chan struct{}) results := make(chan error, len(headers)) go func() { for i, header := range headers { - err := c.verifyHeaderWithCache(chain, state, header, headers[:i], fullVerifies[i]) + err := c.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i]) select { case <-abort: @@ -290,12 +290,12 @@ func (c *Posv) VerifyHeaders(chain consensus.ChainReader, state *state.StateDB, return abort, results } -func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error { +func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { _, check := c.verifiedHeaders.Get(header.Hash()) if check { return nil } - err := c.verifyHeader(chain, state, header, parents, fullVerify) + err := c.verifyHeader(chain, header, parents, fullVerify) if err == nil { c.verifiedHeaders.Add(header.Hash(), true) } @@ -306,7 +306,7 @@ func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, state *state.S // caller may optionally pass in a batch of parents (ascending order) to avoid // looking those up from the database. This is useful for concurrently verifying // a batch of new headers. -func (c *Posv) verifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error { +func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { if header.Number == nil { return errUnknownBlock } @@ -361,14 +361,14 @@ func (c *Posv) verifyHeader(chain consensus.ChainReader, state *state.StateDB, h return err } // All basic checks passed, verify cascading fields - return c.verifyCascadingFields(chain, state, header, parents, fullVerify) + return c.verifyCascadingFields(chain, header, parents, fullVerify) } // verifyCascadingFields verifies all the header fields that are not standalone, // rather depend on a batch of previous headers. The caller may optionally pass // in a batch of parents (ascending order) to avoid looking those up from the // database. This is useful for concurrently verifying a batch of new headers. -func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error { +func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error { // The genesis block is the always valid dead-end number := header.Number.Uint64() if number == 0 { @@ -543,7 +543,7 @@ func (c *Posv) snapshot(chain consensus.ChainReader, number uint64, hash common. // If we're at block zero, make a snapshot if number == 0 { genesis := chain.GetHeaderByNumber(0) - if err := c.VerifyHeader(chain, nil, genesis, true); err != nil { + if err := c.VerifyHeader(chain, genesis, true); err != nil { return nil, err } signers := make([]common.Address, (len(genesis.Extra)-extraVanity-extraSeal)/common.AddressLength) @@ -733,7 +733,7 @@ func (c *Posv) GetValidator(creator common.Address, chain consensus.ChainReader, // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. -func (c *Posv) Prepare(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error { +func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error { // If the block isn't a checkpoint, cast a random vote (good enough for now) header.Coinbase = common.Address{} header.Nonce = types.BlockNonce{} diff --git a/core/blockchain.go b/core/blockchain.go index c2d1cc2c58..48e2661111 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1075,11 +1075,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty seals[i] = true bc.downloadingBlock.Add(block.Hash(), true) } - st, err := bc.State() - if err != nil { - return 0, nil, nil, err - } - abort, results := bc.engine.VerifyHeaders(bc, st, headers, seals) + abort, results := bc.engine.VerifyHeaders(bc, headers, seals) defer close(abort) // Iterate over the blocks and insert when the verifier permits @@ -1256,11 +1252,7 @@ func (bc *BlockChain) PrepareBlock(block *types.Block) (err error) { log.Debug("Stop prepare a block because inserting", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.Header().Validator) return nil } - state, err := bc.State() - if err != nil { - return err - } - err = bc.engine.VerifyHeader(bc, state, block.Header(), false) + err = bc.engine.VerifyHeader(bc, block.Header(), false) if err != nil { return err } diff --git a/core/headerchain.go b/core/headerchain.go index f0ecd73868..9bedc796f0 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -228,7 +228,7 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, state *state.S } seals[len(seals)-1] = true // Last should always be verified to avoid junk - abort, results := hc.engine.VerifyHeaders(hc, state, chain, seals) + abort, results := hc.engine.VerifyHeaders(hc, chain, seals) defer close(abort) // Iterate over the headers and ensure they all check out diff --git a/eth/api_tracer.go b/eth/api_tracer.go index 5f992494b0..07c4457bc3 100644 --- a/eth/api_tracer.go +++ b/eth/api_tracer.go @@ -387,11 +387,7 @@ func (api *PrivateDebugAPI) TraceBlockFromFile(ctx context.Context, file string, // per transaction, dependent on the requestd tracer. func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) { // Create the parent state database - state, err := api.eth.blockchain.State() - if err != nil { - return nil, err - } - if err = api.eth.engine.VerifyHeader(api.eth.blockchain, state, block.Header(), true); err != nil { + if err := api.eth.engine.VerifyHeader(api.eth.blockchain, block.Header(), true); err != nil { return nil, err } parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) diff --git a/eth/handler.go b/eth/handler.go index df2435b080..322a888ade 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -165,11 +165,7 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne manager.downloader = downloader.New(mode, chaindb, manager.eventMux, blockchain, nil, manager.removePeer) validator := func(header *types.Header) error { - state, err := blockchain.State() - if err != nil { - return err - } - return engine.VerifyHeader(blockchain, state, header, true) + return engine.VerifyHeader(blockchain, header, true) } heighter := func() uint64 { return blockchain.CurrentBlock().NumberU64() diff --git a/miner/worker.go b/miner/worker.go index 8b80306e4d..d71b39fe7b 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -552,11 +552,8 @@ func (self *worker) commitNewWork() { if atomic.LoadInt32(&self.mining) == 1 { header.Coinbase = self.coinbase } - state := &state.StateDB{} - if self.current != nil { - state = self.current.state - } - if err := self.engine.Prepare(self.chain, state, header); err != nil { + + if err := self.engine.Prepare(self.chain, header); err != nil { log.Error("Failed to prepare header for new block", "err", err) return } From 7c1e1e0abe683a7ba9169b416749f9bc73c486a3 Mon Sep 17 00:00:00 2001 From: Tuna Date: Sat, 12 Jan 2019 13:22:34 +0700 Subject: [PATCH 19/21] fix unit tests: remove state --- core/block_validator_test.go | 14 +++++--------- core/blockchain_test.go | 6 ++---- light/lightchain_test.go | 3 +-- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/core/block_validator_test.go b/core/block_validator_test.go index d085effdc8..c44def0148 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -48,13 +48,12 @@ func TestHeaderVerification(t *testing.T) { for i := 0; i < len(blocks); i++ { for j, valid := range []bool{true, false} { var results <-chan error - state, _ := chain.State() if valid { engine := ethash.NewFaker() - _, results = engine.VerifyHeaders(chain, state, []*types.Header{headers[i]}, []bool{true}) + _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}) } else { engine := ethash.NewFakeFailer(headers[i].Number.Uint64()) - _, results = engine.VerifyHeaders(chain, state, []*types.Header{headers[i]}, []bool{true}) + _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}) } // Wait for the verification result select { @@ -106,13 +105,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) { var results <-chan error if valid { chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}) - state, _ := chain.State() - _, results = chain.engine.VerifyHeaders(chain, state, headers, seals) + _, results = chain.engine.VerifyHeaders(chain, headers, seals) chain.Stop() } else { chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}) - state, _ := chain.State() - _, results = chain.engine.VerifyHeaders(chain, state, headers, seals) + _, results = chain.engine.VerifyHeaders(chain, headers, seals) chain.Stop() } // Wait for all the verification results @@ -176,8 +173,7 @@ 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() - state, _ := chain.State() - abort, results := chain.engine.VerifyHeaders(chain, state, headers, seals) + abort, results := chain.engine.VerifyHeaders(chain, headers, seals) close(abort) // Deplete the results channel diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 46203a4f37..b752b9ef8d 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -103,8 +103,7 @@ func printChain(bc *BlockChain) { func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { for _, block := range chain { // Try and process the block - st, _ := blockchain.State() - err := blockchain.engine.VerifyHeader(blockchain, st, block.Header(), true) + err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) if err == nil { err = blockchain.validator.ValidateBody(block) } @@ -142,8 +141,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { for _, header := range chain { // Try and validate the header - state, _ := blockchain.State() - if err := blockchain.engine.VerifyHeader(blockchain, state, header, false); err != nil { + if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { return err } // Manually insert the header into the database, but don't reorganise (allows subsequent testing) diff --git a/light/lightchain_test.go b/light/lightchain_test.go index 20e9556b1b..0af7551d41 100644 --- a/light/lightchain_test.go +++ b/light/lightchain_test.go @@ -117,8 +117,7 @@ func testFork(t *testing.T, LightChain *LightChain, i, n int, comparator func(td func testHeaderChainImport(chain []*types.Header, lightchain *LightChain) error { for _, header := range chain { // Try and validate the header - state, _ := lightchain.State() - if err := lightchain.engine.VerifyHeader(lightchain.hc, state, header, true); err != nil { + if err := lightchain.engine.VerifyHeader(lightchain.hc, header, true); err != nil { return err } // Manually insert the header into the database, but don't reorganize (allows subsequent testing) From 196def5fc2237a8402275f8c948d8c5433ac0d1f Mon Sep 17 00:00:00 2001 From: Tuna Date: Sat, 12 Jan 2019 14:47:58 +0700 Subject: [PATCH 20/21] fix validator_test --- contracts/validator/validator_test.go | 84 +++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 5 deletions(-) diff --git a/contracts/validator/validator_test.go b/contracts/validator/validator_test.go index 346066b162..a1cbf6a386 100644 --- a/contracts/validator/validator_test.go +++ b/contracts/validator/validator_test.go @@ -20,15 +20,16 @@ import ( "math/big" "testing" "time" + "math/rand" + "encoding/json" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/contracts" - "github.com/ethereum/go-ethereum/contracts/validator/contract" + contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/crypto" - "math/rand" + "github.com/ethereum/go-ethereum/log" ) var ( @@ -94,7 +95,7 @@ func TestRewardBalance(t *testing.T) { // validatorAddr, _, baseValidator, err := contract.DeployTomoValidator(transactOpts, contractBackend, big.NewInt(50000), big.NewInt(99), big.NewInt(100), big.NewInt(100)) validatorCap := new(big.Int) validatorCap.SetString("50000000000000000000000", 10) - validatorAddr, _, baseValidator, err := contract.DeployTomoValidator( + validatorAddr, _, baseValidator, err := contractValidator.DeployTomoValidator( transactOpts, contractBackend, []common.Address{addr}, @@ -144,7 +145,7 @@ func TestRewardBalance(t *testing.T) { foundationAddr := common.HexToAddress(common.FoudationAddr) totalReward := new(big.Int).SetInt64(15 * 1000) - rewards, err := contracts.GetRewardBalancesRate(foundationAddr, nil, acc3Addr, totalReward) + rewards, err := GetRewardBalancesRate(foundationAddr, acc3Addr, totalReward, baseValidator) if err != nil { t.Error("Fail to get reward balances rate.", err) } @@ -175,3 +176,76 @@ func TestRewardBalance(t *testing.T) { } } + +func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common.Address, totalReward *big.Int, validator *contractValidator.TomoValidator) (map[common.Address]*big.Int, error) { + owner := GetCandidatesOwnerBySigner(validator, masterAddr) + balances := make(map[common.Address]*big.Int) + rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent)) + rewardMaster = new(big.Int).Div(rewardMaster, new(big.Int).SetInt64(100)) + balances[owner] = rewardMaster + // Get voters for masternode. + opts := new(bind.CallOpts) + voters, err := validator.GetVoters(opts, masterAddr) + if err != nil { + log.Crit("Fail to get voters", "error", err) + return nil, err + } + + if len(voters) > 0 { + totalVoterReward := new(big.Int).Mul(totalReward, new(big.Int).SetUint64(common.RewardVoterPercent)) + totalVoterReward = new(big.Int).Div(totalVoterReward, new(big.Int).SetUint64(100)) + totalCap := new(big.Int) + // Get voters capacities. + voterCaps := make(map[common.Address]*big.Int) + for _, voteAddr := range voters { + var voterCap *big.Int + + voterCap, err = validator.GetVoterCap(opts, masterAddr, voteAddr) + if err != nil { + log.Crit("Fail to get vote capacity", "error", err) + } + + totalCap.Add(totalCap, voterCap) + voterCaps[voteAddr] = voterCap + } + if totalCap.Cmp(new(big.Int).SetInt64(0)) > 0 { + for addr, voteCap := range voterCaps { + // Only valid voter has cap > 0. + if voteCap.Cmp(new(big.Int).SetInt64(0)) > 0 { + rcap := new(big.Int).Mul(totalVoterReward, voteCap) + rcap = new(big.Int).Div(rcap, totalCap) + if balances[addr] != nil { + balances[addr].Add(balances[addr], rcap) + } else { + balances[addr] = rcap + } + } + } + } + } + + foudationReward := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardFoundationPercent)) + foudationReward = new(big.Int).Div(foudationReward, new(big.Int).SetInt64(100)) + balances[foudationWalletAddr] = foudationReward + + jsonHolders, err := json.Marshal(balances) + if err != nil { + log.Error("Fail to parse json holders", "error", err) + return nil, err + } + log.Info("Holders reward", "holders", string(jsonHolders), "master node", masterAddr.String()) + + return balances, nil +} + +func GetCandidatesOwnerBySigner(validator *contractValidator.TomoValidator, signerAddr common.Address) common.Address { + owner := signerAddr + opts := new(bind.CallOpts) + owner, err := validator.GetCandidateOwner(opts, signerAddr) + if err != nil { + log.Error("Fail get candidate owner", "error", err) + return owner + } + + return owner +} \ No newline at end of file From 148495ccfd9c170068cfe086c8b9a8727f989c6e Mon Sep 17 00:00:00 2001 From: Tuna Date: Sat, 12 Jan 2019 15:14:24 +0700 Subject: [PATCH 21/21] fix lightchain unit tests --- core/blockchain.go | 6 +----- core/headerchain.go | 3 +-- light/lightchain.go | 6 +----- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 48e2661111..2f0dc16531 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1684,11 +1684,7 @@ Error: %v // because nonces can be verified sparsely, not needing to check each. func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { start := time.Now() - state, err := bc.State() - if err != nil { - return 0, err - } - if i, err := bc.hc.ValidateHeaderChain(chain, state, checkFreq); err != nil { + if i, err := bc.hc.ValidateHeaderChain(chain, checkFreq); err != nil { return i, err } diff --git a/core/headerchain.go b/core/headerchain.go index 9bedc796f0..2d1b0a2a18 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -33,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/hashicorp/golang-lru" - "github.com/ethereum/go-ethereum/core/state" ) const ( @@ -204,7 +203,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er // header writes should be protected by the parent chain mutex individually. type WhCallback func(*types.Header) error -func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, state *state.StateDB, checkFreq int) (int, error) { +func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) (int, error) { // Do a sanity check that the provided chain is actually ordered and linked for i := 1; i < len(chain); i++ { if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() { diff --git a/light/lightchain.go b/light/lightchain.go index a59535049d..2784615d35 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -344,11 +344,7 @@ func (self *LightChain) postChainEvents(events []interface{}) { // chain events when necessary. func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { start := time.Now() - state, err := self.State() - if err != nil { - return 0, err - } - if i, err := self.hc.ValidateHeaderChain(chain, state, checkFreq); err != nil { + if i, err := self.hc.ValidateHeaderChain(chain, checkFreq); err != nil { return i, err }