Skip to content

Commit

Permalink
test: reward validation
Browse files Browse the repository at this point in the history
  • Loading branch information
egonspace committed May 17, 2024
1 parent 24c9a5a commit 4fb0f5b
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 37 deletions.
9 changes: 8 additions & 1 deletion core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,20 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
if receiptSha != header.ReceiptHash {
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
}

// validate engine specific; ethash.engine validate the fees and rewards
err := v.engine.ValidateEngineSpecific(v.bc.chainConfig, header, fees, finalizedOutput)
if err != nil {
return err
}

// Validate the state root against the received state root and throw
// an error if they don't match.
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
}

return v.engine.ValidateEngineSpecific(v.bc.chainConfig, header, fees, finalizedOutput)
return nil
}

// CalcGasLimit computes the gas limit of the next block after parent. It aims
Expand Down
9 changes: 8 additions & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
b.SetCoinbase(common.Address{})
}
b.statedb.Prepare(tx.Hash(), len(b.txs))
receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, b.header.Fees, vm.Config{})
var fees *big.Int
if b.header.Fees != nil {
fees = b.header.Fees // wemix block has `Fees` field
} else {
fees = new(big.Int)

This comment has been minimized.

Copy link
@jed-wemade

jed-wemade May 20, 2024

applyTransaction()에서 fees 값만 갱신하고 header.Fees에 재할당하는 부분이 없어서 b.header.Fees = new(big.Int)로 되어야 할 것 같습니다.

현재 master에서도 계산 후 fee를 assign하는 부분이 없네요.
AddTx(), AddTxWithChain()이 simulated backend와 test 코드에서만 호출되고 있어서 실동작에는 문제가 없던 것으로 보입니다.

fees := new(big.Int)
receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, fees, vm.Config{})
if err != nil {
panic(err)
}
b.txs = append(b.txs, tx)
b.receipts = append(b.receipts, receipt)
}

}
receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, fees, vm.Config{})
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -303,6 +309,7 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
}),
GasLimit: parent.GasLimit(),
Number: new(big.Int).Add(parent.Number(), common.Big1),
Fees: new(big.Int),
Time: time,
}
if chain.Config().IsLondon(header.Number) {
Expand Down
123 changes: 88 additions & 35 deletions wemix/rewards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
package wemix

import (
"bytes"
"crypto/ecdsa"
"encoding/json"
"math/big"
"strings"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
Expand Down Expand Up @@ -175,51 +179,51 @@ func TestDistributeRewards(t *testing.T) {
}
}

func calculateRewardsForTest(config *params.ChainConfig, num, fees *big.Int, addBalance func(common.Address, *big.Int)) (*common.Address, []byte, error) {
rp := &rewardParameters{
rewardAmount: big.NewInt(1e18),
staker: &common.Address{0x11},
ecoSystem: &common.Address{0x22},
maintenance: &common.Address{0x33},
feeCollector: &common.Address{0x44},
members: []*wemixMember{
{
Staker: common.HexToAddress("0x02b4b2d83786c8ee315db2ddac704794850d2149"),
Reward: common.HexToAddress("0x02b4b2d83786c8ee315db2ddac704794850d2149"),
Stake: hexToBigInt("0x1a784379d99db42000000"),
},
{
Staker: common.HexToAddress("0xb16d2494fddfa4c000deaf642d47673e5ca74e07"),
Reward: common.HexToAddress("0xb16d2494fddfa4c000deaf642d47673e5ca74e07"),
Stake: hexToBigInt("0xe8ef1e96ae3897800000"),
},
{
Staker: common.HexToAddress("0x452893ed818c0e3ea6f415aeab8ef08778087fc6"),
Reward: common.HexToAddress("0x452893ed818c0e3ea6f415aeab8ef08778087fc6"),
Stake: hexToBigInt("0xc92b9a6adc4825c00000"),
},
},
blocksPer: 1,
distributionMethod: []*big.Int{big.NewInt(4000), big.NewInt(1000), big.NewInt(2500), big.NewInt(2500)},
func makeCalculateRewardFunc(rp *rewardParameters) func(config *params.ChainConfig, num, fees *big.Int, addBalance func(common.Address, *big.Int)) (*common.Address, []byte, error) {
return func(config *params.ChainConfig, num, fees *big.Int, addBalance func(common.Address, *big.Int)) (*common.Address, []byte, error) {
return calculateRewardsWithParams(config, rp, num, fees, addBalance)
}
}

return calculateRewardsWithParams(config, rp, num, fees, addBalance)
func makeSignBlockFunc(privateKey *ecdsa.PrivateKey) func(height *big.Int, hash common.Hash) (common.Address, []byte, error) {
return func(height *big.Int, hash common.Hash) (coinbase common.Address, sig []byte, err error) {
data := append(height.Bytes(), hash.Bytes()...)
data = crypto.Keccak256(data)
sig, _ = crypto.Sign(data, privateKey)
return crypto.PubkeyToAddress(privateKey.PublicKey), sig, nil
}
}

func verifyBlockSigForTest(height *big.Int, coinbase common.Address, nodeId []byte, hash common.Hash, sig []byte, checkMinerLimit bool) bool {
var data []byte
data = append(height.Bytes(), hash.Bytes()...)
data = crypto.Keccak256(data)
pubKey, err := crypto.SigToPub(data, sig)
if err != nil {
return false
}
signer := crypto.PubkeyToAddress(*pubKey)
if err != nil || !bytes.Equal(coinbase.Bytes(), signer.Bytes()) {
return false
}
return true
}

func TestRewardValidation(t *testing.T) {
// use wemix consensus
params.ConsensusMethod = params.ConsensusPoA
wemixminer.CalculateRewardsFunc = calculateRewardsForTest

var (
db = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
funds = big.NewInt(100000000000000)
deleteAddr = common.Address{1}
gspec = &core.Genesis{
Config: &params.ChainConfig{
ChainID: big.NewInt(1),
ChainID: big.NewInt(1),
LondonBlock: common.Big0,
BriocheBlock: common.Big0,
Brioche: &params.BriocheConfig{
BlockReward: big.NewInt(100),
FirstHalvingBlock: big.NewInt(0),
Expand All @@ -231,18 +235,67 @@ func TestRewardValidation(t *testing.T) {
Alloc: core.GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: big.NewInt(0)}},
}
genesis = gspec.MustCommit(db)
signer = types.LatestSigner(gspec.Config)
)

rp := &rewardParameters{
rewardAmount: big.NewInt(1e18),
staker: &common.Address{0x11},
ecoSystem: &common.Address{0x22},
maintenance: &common.Address{0x33},
feeCollector: &common.Address{0x44},
members: []*wemixMember{
{
Staker: common.HexToAddress("0x02b4b2d83786c8ee315db2ddac704794850d2149"),
Reward: common.HexToAddress("0x02b4b2d83786c8ee315db2ddac704794850d2149"),
Stake: hexToBigInt("0x1a784379d99db42000000"),
},
{
Staker: common.HexToAddress("0xb16d2494fddfa4c000deaf642d47673e5ca74e07"),
Reward: common.HexToAddress("0xb16d2494fddfa4c000deaf642d47673e5ca74e07"),
Stake: hexToBigInt("0xe8ef1e96ae3897800000"),
},
{
Staker: common.HexToAddress("0x452893ed818c0e3ea6f415aeab8ef08778087fc6"),
Reward: common.HexToAddress("0x452893ed818c0e3ea6f415aeab8ef08778087fc6"),
Stake: hexToBigInt("0xc92b9a6adc4825c00000"),
},
},
blocksPer: 1,
distributionMethod: []*big.Int{big.NewInt(4000), big.NewInt(1000), big.NewInt(2500), big.NewInt(2500)},
}

wemixminer.CalculateRewardsFunc = makeCalculateRewardFunc(rp)
wemixminer.SignBlockFunc = makeSignBlockFunc(key)
wemixminer.VerifyBlockSigFunc = verifyBlockSigForTest

blockchain, _ := core.NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()

gspec.Config.Brioche.BlockReward = big.NewInt(200)
// TODO: core.GenerateChain does not make a wemix block including Fees, Rewards etc.
// TODO: implement wemix.GenerateChain function
blocks, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 1, nil)
byzantineConfig := &params.ChainConfig{
ChainID: gspec.Config.ChainID,
LondonBlock: gspec.Config.LondonBlock,
BriocheBlock: gspec.Config.BriocheBlock,
Brioche: &params.BriocheConfig{
BlockReward: big.NewInt(200), // different reward!!
FirstHalvingBlock: gspec.Config.Brioche.FirstHalvingBlock,
HalvingPeriod: gspec.Config.Brioche.HalvingPeriod,
NoRewardHereafter: gspec.Config.Brioche.NoRewardHereafter,
HalvingTimes: gspec.Config.Brioche.HalvingTimes,
HalvingRate: gspec.Config.Brioche.HalvingRate,
}}
blocks, _ := core.GenerateChain(byzantineConfig, genesis, ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) {
tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1), params.TxGas, gen.BaseFee(), nil), signer, key)
if err != nil {
panic(err)
}
gen.AddTx(tx)
})

if _, err := blockchain.InsertChain(blocks); err != nil {
t.Fatal(err)
if !strings.HasPrefix(err.Error(), "invalid rewards") {
t.Fatal(err)
}
}
}

Expand Down

0 comments on commit 4fb0f5b

Please sign in to comment.