diff --git a/contracts/smcReader.go b/contracts/smcReader.go deleted file mode 100644 index 0363b1ac97..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 -} \ No newline at end of file diff --git a/contracts/smcUtils.go b/contracts/smcUtils.go index 3aeefe8962..66f01af2c0 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) } \ No newline at end of file diff --git a/contracts/validatorReader.go b/contracts/validatorReader.go new file mode 100644 index 0000000000..01a16ede88 --- /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.XDCValidatorABI)) + 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 +} \ No newline at end of file