Merge pull request #400 from ngtuna/smc-reader-merge

Smc reader merge
This commit is contained in:
Tuna 2019-01-12 15:15:18 +07:00 committed by GitHub
commit 702a8ed560
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 609 additions and 83 deletions

View file

@ -1256,6 +1256,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
}) })
} }
Fatalf("Only support posv consensus")
} }
if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)

View file

@ -778,7 +778,7 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
} }
header.Extra = header.Extra[:extraVanity] header.Extra = header.Extra[:extraVanity]
masternodes := snap.GetSigners() 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 { if c.HookPenalty != nil {
penMasternodes, err := c.HookPenalty(chain, number) penMasternodes, err := c.HookPenalty(chain, number)
if err != nil { if err != nil {

View file

@ -0,0 +1,33 @@
package contracts
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
)
var (
slotBlockSignerMapping = map[string]uint64{
"blockSigners": 0,
"blocks": 1,
}
)
func GetSigners(statedb *state.StateDB, block *types.Block) []common.Address {
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()))
}
return rets
}

View file

@ -0,0 +1,37 @@
package contracts
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
)
var (
slotRandomizeMapping = map[string]uint64{
"randomSecret": 0,
"randomOpening": 1,
}
)
func GetSecret(statedb *state.StateDB, address common.Address) [][32]byte {
slot := slotRandomizeMapping["randomSecret"]
locSecret := getLocMappingAtKey(address.Hash(), slot)
arrLength := statedb.GetState(common.HexToAddress(common.RandomizeSMC), common.BigToHash(locSecret))
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)
}
return rets
}
func GetOpening(statedb *state.StateDB, address common.Address) [32]byte {
slot := slotRandomizeMapping["randomOpening"]
locOpening := getLocMappingAtKey(address.Hash(), slot)
ret := statedb.GetState(common.HexToAddress(common.RandomizeSMC), common.BigToHash(locOpening))
return ret
}

34
contracts/smcUtils.go Normal file
View file

@ -0,0 +1,34 @@
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) *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)
}

281
contracts/test.go Normal file
View file

@ -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)
//}

View file

@ -31,20 +31,19 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/accounts" "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"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/posv" "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"
"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/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "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 ( const (
@ -199,7 +198,12 @@ func BuildTxOpeningRandomize(nonce uint64, randomizeAddr common.Address, randomi
} }
// Get signers signed for blockNumber from blockSigner contract. // Get signers signed for blockNumber from blockSigner contract.
func GetSignersFromContract(addrBlockSigner common.Address, client bind.ContractBackend, blockHash common.Hash) ([]common.Address, error) { func GetSignersFromContract(state *state.StateDB, block *types.Block) ([]common.Address, error) {
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) blockSigner, err := contract.NewBlockSigner(addrBlockSigner, client)
if err != nil { if err != nil {
log.Error("Fail get instance of blockSigner", "error", err) log.Error("Fail get instance of blockSigner", "error", err)
@ -219,18 +223,15 @@ func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common
randomize, err := randomizeContract.NewTomoRandomize(common.HexToAddress(common.RandomizeSMC), client) randomize, err := randomizeContract.NewTomoRandomize(common.HexToAddress(common.RandomizeSMC), client)
if err != nil { if err != nil {
log.Error("Fail to get instance of randomize", "error", err) log.Error("Fail to get instance of randomize", "error", err)
return -1, err
} }
opts := new(bind.CallOpts) opts := new(bind.CallOpts)
secrets, err := randomize.GetSecret(opts, addrMasternode) secrets, err := randomize.GetSecret(opts, addrMasternode)
if err != nil { if err != nil {
log.Error("Fail get secrets from randomize", "error", err) log.Error("Fail get secrets from randomize", "error", err)
return -1, err
} }
opening, err := randomize.GetOpening(opts, addrMasternode) opening, err := randomize.GetOpening(opts, addrMasternode)
if err != nil { if err != nil {
log.Error("Fail get opening from randomize", "error", err) log.Error("Fail get opening from randomize", "error", err)
return -1, err
} }
return DecryptRandomizeFromSecretsAndOpening(secrets, opening) return DecryptRandomizeFromSecretsAndOpening(secrets, opening)
@ -420,46 +421,28 @@ func CalculateRewardForSigner(chainReward *big.Int, signers map[common.Address]*
return resultSigners, nil return resultSigners, nil
} }
func GetCandidatesOwnerBySigner(validator *contractValidator.TomoValidator, signerAddr common.Address) common.Address { // Get candidate owner by address.
owner := signerAddr func GetCandidatesOwnerBySigner(state *state.StateDB, signerAddr common.Address) common.Address {
opts := new(bind.CallOpts) owner := GetCandidateOwner(state, signerAddr)
owner, err := validator.GetCandidateOwner(opts, signerAddr)
if err != nil {
log.Error("Fail get candidate owner", "error", err)
return owner return owner
} }
return owner 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)
// 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)
if err != nil { if err != nil {
return err, nil return err, nil
} }
if len(rewards) > 0 {
for holder, reward := range rewards {
state.AddBalance(holder, reward)
}
}
return nil, rewards return nil, rewards
} }
// Get reward balance rates for master node, founder and holders. func GetRewardBalancesRate(foundationWalletAddr common.Address, state *state.StateDB, masterAddr common.Address, totalReward *big.Int) (map[common.Address]*big.Int, error) {
func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common.Address, totalReward *big.Int, validator *contractValidator.TomoValidator) (map[common.Address]*big.Int, error) { owner := GetCandidatesOwnerBySigner(state, masterAddr)
owner := GetCandidatesOwnerBySigner(validator, masterAddr)
balances := make(map[common.Address]*big.Int) balances := make(map[common.Address]*big.Int)
rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent)) rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent))
rewardMaster = new(big.Int).Div(rewardMaster, new(big.Int).SetInt64(100)) rewardMaster = new(big.Int).Div(rewardMaster, new(big.Int).SetInt64(100))
balances[owner] = rewardMaster balances[owner] = rewardMaster
// Get voters for masternode. // Get voters for masternode.
opts := new(bind.CallOpts) voters := GetVoters(state, masterAddr)
voters, err := validator.GetVoters(opts, masterAddr)
if err != nil {
log.Crit("Fail to get voters", "error", err)
return nil, err
}
if len(voters) > 0 { if len(voters) > 0 {
totalVoterReward := new(big.Int).Mul(totalReward, new(big.Int).SetUint64(common.RewardVoterPercent)) totalVoterReward := new(big.Int).Mul(totalReward, new(big.Int).SetUint64(common.RewardVoterPercent))
@ -468,13 +451,7 @@ func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common
// Get voters capacities. // Get voters capacities.
voterCaps := make(map[common.Address]*big.Int) voterCaps := make(map[common.Address]*big.Int)
for _, voteAddr := range voters { for _, voteAddr := range voters {
var voterCap *big.Int voterCap := GetVoterCap(state, masterAddr, voteAddr)
voterCap, err = validator.GetVoterCap(opts, masterAddr, voteAddr)
if err != nil {
log.Crit("Fail to get vote capacity", "error", err)
}
totalCap.Add(totalCap, voterCap) totalCap.Add(totalCap, voterCap)
voterCaps[voteAddr] = voterCap voterCaps[voteAddr] = voterCap
} }
@ -494,9 +471,9 @@ func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common
} }
} }
foudationReward := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardFoundationPercent)) foundationReward := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardFoundationPercent))
foudationReward = new(big.Int).Div(foudationReward, new(big.Int).SetInt64(100)) foundationReward = new(big.Int).Div(foundationReward, new(big.Int).SetInt64(100))
balances[foudationWalletAddr] = foudationReward balances[foundationWalletAddr] = foundationReward
jsonHolders, err := json.Marshal(balances) jsonHolders, err := json.Marshal(balances)
if err != nil { if err != nil {

View file

@ -20,15 +20,16 @@ import (
"math/big" "math/big"
"testing" "testing"
"time" "time"
"math/rand"
"encoding/json"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts" contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
"github.com/ethereum/go-ethereum/contracts/validator/contract"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"math/rand" "github.com/ethereum/go-ethereum/log"
) )
var ( 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)) // validatorAddr, _, baseValidator, err := contract.DeployTomoValidator(transactOpts, contractBackend, big.NewInt(50000), big.NewInt(99), big.NewInt(100), big.NewInt(100))
validatorCap := new(big.Int) validatorCap := new(big.Int)
validatorCap.SetString("50000000000000000000000", 10) validatorCap.SetString("50000000000000000000000", 10)
validatorAddr, _, baseValidator, err := contract.DeployTomoValidator( validatorAddr, _, baseValidator, err := contractValidator.DeployTomoValidator(
transactOpts, transactOpts,
contractBackend, contractBackend,
[]common.Address{addr}, []common.Address{addr},
@ -144,7 +145,7 @@ func TestRewardBalance(t *testing.T) {
foundationAddr := common.HexToAddress(common.FoudationAddr) foundationAddr := common.HexToAddress(common.FoudationAddr)
totalReward := new(big.Int).SetInt64(15 * 1000) totalReward := new(big.Int).SetInt64(15 * 1000)
rewards, err := contracts.GetRewardBalancesRate(foundationAddr, acc3Addr, totalReward, baseValidator) rewards, err := GetRewardBalancesRate(foundationAddr, acc3Addr, totalReward, baseValidator)
if err != nil { if err != nil {
t.Error("Fail to get reward balances rate.", err) 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
}

View file

@ -0,0 +1,88 @@
package contracts
import (
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
)
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,
}
)
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)
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()))
}
return rets
}
func GetCandidateOwner(statedb *state.StateDB, candidate common.Address) common.Address {
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))
return common.HexToAddress(ret.Hex())
}
func GetCandidateCap(statedb *state.StateDB, parsed abi.ABI, candidate common.Address) string {
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))
return ret.Hex()
}
func GetVoters(statedb *state.StateDB, candidate common.Address) []common.Address {
//mapping(address => address[]) voters;
slot := slotValidatorMapping["voters"]
locVoters := getLocMappingAtKey(candidate.Hash(), slot)
arrLength := statedb.GetState(common.HexToAddress(common.MasternodeVotingSMC), common.BigToHash(locVoters))
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()))
}
return rets
}
func GetVoterCap(state *state.StateDB, candidate, voter common.Address) *big.Int {
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))
return ret.Big()
}

View file

@ -48,7 +48,6 @@ func TestHeaderVerification(t *testing.T) {
for i := 0; i < len(blocks); i++ { for i := 0; i < len(blocks); i++ {
for j, valid := range []bool{true, false} { for j, valid := range []bool{true, false} {
var results <-chan error var results <-chan error
if valid { if valid {
engine := ethash.NewFaker() engine := ethash.NewFaker()
_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true}) _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true})
@ -104,7 +103,6 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
// also an invalid chain (enough if one arbitrary block is invalid). // also an invalid chain (enough if one arbitrary block is invalid).
for i, valid := range []bool{true, false} { for i, valid := range []bool{true, false} {
var results <-chan error var results <-chan error
if valid { if valid {
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}) chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
_, results = chain.engine.VerifyHeaders(chain, headers, seals) _, results = chain.engine.VerifyHeaders(chain, headers, seals)
@ -175,7 +173,6 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
// Start the verifications and immediately abort // Start the verifications and immediately abort
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}) chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{})
defer chain.Stop() defer chain.Stop()
abort, results := chain.engine.VerifyHeaders(chain, headers, seals) abort, results := chain.engine.VerifyHeaders(chain, headers, seals)
close(abort) close(abort)

View file

@ -34,10 +34,9 @@ import (
"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/consensus/posv"
"github.com/ethereum/go-ethereum/contracts" "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"
"github.com/ethereum/go-ethereum/core/bloombits" "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/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
@ -53,6 +52,7 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/core/state"
) )
type LesServer interface { type LesServer interface {
@ -244,9 +244,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
// Hook scans for bad masternodes and decide to penalty them // Hook scans for bad masternodes and decide to penalty them
c.HookPenalty = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) { c.HookPenalty = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) {
client, err := eth.blockchain.GetClient() canonicalState, err := eth.blockchain.State()
if err != nil { if canonicalState == nil || err != nil {
return nil, err 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 prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch
if prevEpoc >= 0 { if prevEpoc >= 0 {
@ -254,12 +254,13 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
prevHeader := chain.GetHeaderByNumber(prevEpoc) prevHeader := chain.GetHeaderByNumber(prevEpoc)
penSigners := c.GetMasternodes(chain, prevHeader) penSigners := c.GetMasternodes(chain, prevHeader)
if len(penSigners) > 0 { if len(penSigners) > 0 {
blockSignerAddr := common.HexToAddress(common.BlockSigners)
// Loop for each block to check missing sign. // Loop for each block to check missing sign.
for i := prevEpoc; i < blockNumberEpoc; i++ { 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 { if len(penSigners) > 0 {
signedMasternodes, err := contracts.GetSignersFromContract(blockSignerAddr, client, blockHeader.Hash()) signedMasternodes, err := contracts.GetSignersFromContract(canonicalState, block)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -287,25 +288,28 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
// Hook calculates reward for masternodes // Hook calculates reward for masternodes
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) { c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) {
client, err := eth.blockchain.GetClient() canonicalState, err := eth.blockchain.State()
if err != nil { if canonicalState == nil || err != nil {
log.Crit("Fail to connect IPC client for blockSigner", "error", err) log.Crit("Can't get state at head of canonical chain", "head number", header.Number.Uint64(), "err", err)
} }
number := header.Number.Uint64() number := header.Number.Uint64()
rCheckpoint := chain.Config().Posv.RewardCheckpoint rCheckpoint := chain.Config().Posv.RewardCheckpoint
foudationWalletAddr := chain.Config().Posv.FoudationWalletAddr foundationWalletAddr := chain.Config().Posv.FoudationWalletAddr
if foudationWalletAddr == (common.Address{}) { if foundationWalletAddr == (common.Address{}) {
log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr) log.Error("Foundation Wallet Address is empty", "error", foundationWalletAddr)
return err, nil
} }
rewards := make(map[string]interface{}) 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() start := time.Now()
// Get signers in blockSigner smartcontract.
// Get reward inflation. // Get reward inflation.
chainReward := new(big.Int).Mul(new(big.Int).SetUint64(chain.Config().Posv.Reward), new(big.Int).SetUint64(params.Ether)) 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) chainReward = rewardInflation(chainReward, number, common.BlocksPerYear)
totalSigner := new(uint64) totalSigner := new(uint64)
signers, err := contracts.GetRewardForCheckpoint(c, chain, number, rCheckpoint, totalSigner) signers, err := contracts.GetRewardForCheckpoint(c, chain, number, rCheckpoint, totalSigner)
log.Debug("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) log.Debug("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
if err != nil { if err != nil {
log.Crit("Fail to get signers for reward checkpoint", "error", err) log.Crit("Fail to get signers for reward checkpoint", "error", err)
@ -315,19 +319,19 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if err != nil { if err != nil {
log.Crit("Fail to calculate reward for signers", "error", err) 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. // Add reward for coin holders.
voterResults := make(map[common.Address]interface{}) voterResults := make(map[common.Address]interface{})
if len(signers) > 0 { if len(signers) > 0 {
for signer, calcReward := range rewardSigners { for signer, calcReward := range rewardSigners {
err, rewards := contracts.CalculateRewardForHolders(foudationWalletAddr, validator, state, signer, calcReward) err, rewards := contracts.CalculateRewardForHolders(foundationWalletAddr, canonicalState, signer, calcReward)
if err != nil { if err != nil {
log.Crit("Fail to calculate reward for holders.", "error", err) 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 voterResults[signer] = rewards
} }
} }
@ -353,6 +357,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
} }
return nil return nil
} }
eth.txPool.IsMasterNode = func(address common.Address) bool { eth.txPool.IsMasterNode = func(address common.Address) bool {
currentHeader := eth.blockchain.CurrentHeader() currentHeader := eth.blockchain.CurrentHeader()
snap, err := c.GetSnapshot(eth.blockchain, currentHeader) snap, err := c.GetSnapshot(eth.blockchain, currentHeader)
@ -404,6 +409,7 @@ func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chai
if chainConfig.Posv != nil { if chainConfig.Posv != nil {
return posv.New(chainConfig.Posv, db) return posv.New(chainConfig.Posv, db)
} }
// Otherwise assume proof-of-work // Otherwise assume proof-of-work
switch { switch {
case config.PowMode == ethash.ModeFake: case config.PowMode == ethash.ModeFake:

View file

@ -855,22 +855,19 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
} }
fields["uncles"] = uncleHashes 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 signers []common.Address
var filterSigners []common.Address var filterSigners []common.Address
finality := int32(0) finality := int32(0)
if b.Number().Int64() > 0 { if b.Number().Int64() > 0 {
engine := s.b.GetEngine() engine := s.b.GetEngine()
addrBlockSigner := common.HexToAddress(common.BlockSigners) blockNr := rpc.BlockNumber(b.Number().Int64())
signers, err = contracts.GetSignersFromContract(addrBlockSigner, client, b.Hash()) state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
if state == nil || err != nil {
return nil, err
}
signers, err = contracts.GetSignersFromContract(state, b)
if err != nil { if err != nil {
log.Error("Fail to get signers from block signer SC.", "error", err) log.Error("Fail to get signers from block signer SC.", "error", err)
return nil, err
} }
// Get block epoc latest. // Get block epoc latest.
if s.b.ChainConfig().Posv != nil { if s.b.ChainConfig().Posv != nil {

View file

@ -552,6 +552,7 @@ func (self *worker) commitNewWork() {
if atomic.LoadInt32(&self.mining) == 1 { if atomic.LoadInt32(&self.mining) == 1 {
header.Coinbase = self.coinbase header.Coinbase = self.coinbase
} }
if err := self.engine.Prepare(self.chain, header); err != nil { if err := self.engine.Prepare(self.chain, header); err != nil {
log.Error("Failed to prepare header for new block", "err", err) log.Error("Failed to prepare header for new block", "err", err)
return return