Compare commits
23 Commits
versa_debu
...
bc-fusion-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bba0e11e9 | ||
|
|
7ade1d2a5d | ||
|
|
e2e2ac750c | ||
|
|
85c6750592 | ||
|
|
7466f0a075 | ||
|
|
64a57a3e2a | ||
|
|
e5822640c6 | ||
|
|
432085ea62 | ||
|
|
aab5ad94b8 | ||
|
|
c0df5e7000 | ||
|
|
167da21801 | ||
|
|
08f75ca23f | ||
|
|
6685f68995 | ||
|
|
d4f7313760 | ||
|
|
94b68156c8 | ||
|
|
ab8793ae9f | ||
|
|
6744d7c15f | ||
|
|
3414e5672a | ||
|
|
8f3c525adc | ||
|
|
3e9e6423c0 | ||
|
|
5743b067ba | ||
|
|
d3f882d799 | ||
|
|
030e41607e |
2
.github/workflows/build-test.yml
vendored
2
.github/workflows/build-test.yml
vendored
@@ -47,5 +47,3 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
go mod download
|
go mod download
|
||||||
make geth
|
make geth
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
|||||||
${{ runner.os }}-go-
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
- run: |
|
- run: |
|
||||||
go mod download
|
go mod tidy
|
||||||
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v3
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
|||||||
1
.github/workflows/unit-test.yml
vendored
1
.github/workflows/unit-test.yml
vendored
@@ -52,4 +52,3 @@ jobs:
|
|||||||
git submodule update --init --depth 1 --recursive
|
git submodule update --init --depth 1 --recursive
|
||||||
go mod download
|
go mod download
|
||||||
make test
|
make test
|
||||||
|
|
||||||
|
|||||||
@@ -2127,7 +2127,7 @@ func TestGolangBindings(t *testing.T) {
|
|||||||
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
|
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/tendermint@v0.0.0", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/tendermint@v0.31.15") // Repo root
|
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/tendermint@v0.0.0", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/tendermint@v0.31.16") // Repo root
|
||||||
replacer.Dir = pkg
|
replacer.Dir = pkg
|
||||||
if out, err := replacer.CombinedOutput(); err != nil {
|
if out, err := replacer.CombinedOutput(); err != nil {
|
||||||
t.Fatalf("failed to replace tendermint dependency to bnb-chain source: %v\n%s", err, out)
|
t.Fatalf("failed to replace tendermint dependency to bnb-chain source: %v\n%s", err, out)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -15,6 +16,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/v4/io/prompt"
|
"github.com/prysmaticlabs/prysm/v4/io/prompt"
|
||||||
"github.com/prysmaticlabs/prysm/v4/proto/eth/service"
|
"github.com/prysmaticlabs/prysm/v4/proto/eth/service"
|
||||||
|
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts"
|
"github.com/prysmaticlabs/prysm/v4/validator/accounts"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
|
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/accounts/petnames"
|
"github.com/prysmaticlabs/prysm/v4/validator/accounts/petnames"
|
||||||
@@ -26,6 +28,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/signer/core"
|
"github.com/ethereum/go-ethereum/signer/core"
|
||||||
)
|
)
|
||||||
@@ -47,6 +50,10 @@ var (
|
|||||||
Usage: "Password file path for the imported BLS account , which contains the password to get the private key by decrypting the keystore file",
|
Usage: "Password file path for the imported BLS account , which contains the password to get the private key by decrypting the keystore file",
|
||||||
Category: flags.AccountCategory,
|
Category: flags.AccountCategory,
|
||||||
}
|
}
|
||||||
|
chainIdFlag = &cli.Int64Flag{
|
||||||
|
Name: "chain-id",
|
||||||
|
Usage: "The chain id of the network that the validator will be created at",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -189,6 +196,22 @@ Print summary of existing BLS accounts in the current BLS wallet.`,
|
|||||||
|
|
||||||
Delete the selected BLS account from the BLS wallet.`,
|
Delete the selected BLS account from the BLS wallet.`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "generate-proof",
|
||||||
|
Usage: "Generate ownership proof for the selected BLS account from the BLS wallet",
|
||||||
|
Action: blsAccountGenerateProof,
|
||||||
|
ArgsUsage: "<BLS pubkey>",
|
||||||
|
Category: "BLS ACCOUNT COMMANDS",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
utils.DataDirFlag,
|
||||||
|
utils.BLSPasswordFileFlag,
|
||||||
|
chainIdFlag,
|
||||||
|
},
|
||||||
|
Description: `
|
||||||
|
geth bls account generate-proof
|
||||||
|
|
||||||
|
Generate ownership proof for the selected BLS account from the BLS wallet. The proof is used to prove the ownership of the BLS account when creating validator on BSC after feynman upgrade.`,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -608,3 +631,79 @@ func blsAccountDelete(ctx *cli.Context) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blsAccountGenerateProof generate ownership proof for a selected BLS account.
|
||||||
|
func blsAccountGenerateProof(ctx *cli.Context) error {
|
||||||
|
if ctx.Args().Len() == 0 {
|
||||||
|
utils.Fatalf("No BLS account specified.")
|
||||||
|
}
|
||||||
|
var filteredPubKeys []bls.PublicKey
|
||||||
|
for _, str := range ctx.Args().Slice() {
|
||||||
|
pkString := str
|
||||||
|
if strings.Contains(pkString, "0x") {
|
||||||
|
pkString = pkString[2:]
|
||||||
|
}
|
||||||
|
pubKeyBytes, err := hex.DecodeString(pkString)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Could not decode string %s as hex.", pkString)
|
||||||
|
}
|
||||||
|
blsPublicKey, err := bls.PublicKeyFromBytes(pubKeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("%#x is not a valid BLS public key.", pubKeyBytes)
|
||||||
|
}
|
||||||
|
filteredPubKeys = append(filteredPubKeys, blsPublicKey)
|
||||||
|
}
|
||||||
|
if len(filteredPubKeys) > 1 {
|
||||||
|
utils.Fatalf("Only support one BLS account specified.")
|
||||||
|
}
|
||||||
|
pubkeyBz := filteredPubKeys[0].Marshal()
|
||||||
|
|
||||||
|
cfg := gethConfig{Node: defaultNodeConfig()}
|
||||||
|
// Load config file.
|
||||||
|
if file := ctx.String(configFileFlag.Name); file != "" {
|
||||||
|
if err := loadConfig(file, &cfg); err != nil {
|
||||||
|
utils.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
utils.SetNodeConfig(ctx, &cfg.Node)
|
||||||
|
|
||||||
|
walletDir := filepath.Join(cfg.Node.DataDir, BLSWalletPath)
|
||||||
|
dirExists, err := wallet.Exists(walletDir)
|
||||||
|
if err != nil || !dirExists {
|
||||||
|
utils.Fatalf("BLS wallet not exists.")
|
||||||
|
}
|
||||||
|
|
||||||
|
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
|
||||||
|
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
|
||||||
|
WalletDir: walletDir,
|
||||||
|
WalletPassword: walletPassword,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Open BLS wallet failed: %v.", err)
|
||||||
|
}
|
||||||
|
km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Initialize key manager failed: %v.", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
chainIdInt64 := ctx.Int64(chainIdFlag.Name)
|
||||||
|
if chainIdInt64 == 0 {
|
||||||
|
utils.Fatalf("Chain id is required.")
|
||||||
|
}
|
||||||
|
chainId := new(big.Int).SetInt64(chainIdInt64)
|
||||||
|
paddedChainIdBytes := make([]byte, 32)
|
||||||
|
copy(paddedChainIdBytes[32-len(chainId.Bytes()):], chainId.Bytes())
|
||||||
|
msgHash := crypto.Keccak256(append(pubkeyBz, paddedChainIdBytes...))
|
||||||
|
|
||||||
|
req := &validatorpb.SignRequest{
|
||||||
|
PublicKey: pubkeyBz,
|
||||||
|
SigningRoot: msgHash,
|
||||||
|
}
|
||||||
|
sig, err := km.Sign(context.Background(), req)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Generate signature failed: %v.", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Proof: %#x\n", sig.Marshal())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
237
consensus/parlia/feynmanfork.go
Normal file
237
consensus/parlia/feynmanfork.go
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
package parlia
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/heap"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/systemcontracts"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: SecondsPerDay represents the seconds in a day, it should be 86400
|
||||||
|
// We set it to 60 for testing purpose and we will change it back to 86400 when launching
|
||||||
|
// const SecondsPerDay uint64 = 86400
|
||||||
|
const SecondsPerDay uint64 = 60
|
||||||
|
|
||||||
|
// the params should be two blocks' time(timestamp)
|
||||||
|
func sameDayInUTC(first, second uint64) bool {
|
||||||
|
return first/SecondsPerDay == second/SecondsPerDay
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBreatheBlock(lastBlockTime, blockTime uint64) bool {
|
||||||
|
return lastBlockTime != 0 && !sameDayInUTC(lastBlockTime, blockTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
// initializeFeynmanContract initialize new contracts of Feynman fork
|
||||||
|
func (p *Parlia) initializeFeynmanContract(state *state.StateDB, header *types.Header, chain core.ChainContext,
|
||||||
|
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
|
||||||
|
) error {
|
||||||
|
// method
|
||||||
|
method := "initialize"
|
||||||
|
|
||||||
|
// initialize contracts
|
||||||
|
contracts := []string{
|
||||||
|
systemcontracts.StakeHubContract,
|
||||||
|
systemcontracts.GovernorContract,
|
||||||
|
systemcontracts.GovTokenContract,
|
||||||
|
systemcontracts.TimelockContract,
|
||||||
|
}
|
||||||
|
// get packed data
|
||||||
|
data, err := p.stakeHubABI.Pack(method)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to pack tx for initialize feynman contracts", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, c := range contracts {
|
||||||
|
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0)
|
||||||
|
// apply message
|
||||||
|
log.Info("initialize feynman contract", "block number", header.Number.Uint64(), "contract", c)
|
||||||
|
err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValidatorItem struct {
|
||||||
|
address common.Address
|
||||||
|
votingPower *big.Int
|
||||||
|
voteAddress []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// An ValidatorHeap is a max-heap of validator's votingPower.
|
||||||
|
type ValidatorHeap []ValidatorItem
|
||||||
|
|
||||||
|
func (h *ValidatorHeap) Len() int { return len(*h) }
|
||||||
|
|
||||||
|
func (h *ValidatorHeap) Less(i, j int) bool {
|
||||||
|
// We want topK validators with max voting power, so we need a max-heap
|
||||||
|
if (*h)[i].votingPower.Cmp((*h)[j].votingPower) == 0 {
|
||||||
|
return (*h)[i].address.Hex() < (*h)[j].address.Hex()
|
||||||
|
} else {
|
||||||
|
return (*h)[i].votingPower.Cmp((*h)[j].votingPower) == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ValidatorHeap) Swap(i, j int) { (*h)[i], (*h)[j] = (*h)[j], (*h)[i] }
|
||||||
|
|
||||||
|
func (h *ValidatorHeap) Push(x interface{}) {
|
||||||
|
*h = append(*h, x.(ValidatorItem))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ValidatorHeap) Pop() interface{} {
|
||||||
|
old := *h
|
||||||
|
n := len(old)
|
||||||
|
x := old[n-1]
|
||||||
|
*h = old[0 : n-1]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parlia) updateValidatorSetV2(state *state.StateDB, header *types.Header, chain core.ChainContext,
|
||||||
|
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
|
||||||
|
) error {
|
||||||
|
// 1. get all validators and its voting power
|
||||||
|
blockNr := rpc.BlockNumberOrHashWithHash(header.ParentHash, false)
|
||||||
|
validatorItems, err := p.getValidatorElectionInfo(blockNr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
maxElectedValidators, err := p.getMaxElectedValidators(blockNr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. sort by voting power
|
||||||
|
eValidators, eVotingPowers, eVoteAddrs := getTopValidatorsByVotingPower(validatorItems, maxElectedValidators)
|
||||||
|
|
||||||
|
// 3. update validator set to system contract
|
||||||
|
method := "updateValidatorSetV2"
|
||||||
|
data, err := p.validatorSetABI.Pack(method, eValidators, eVotingPowers, eVoteAddrs)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to pack tx for updateValidatorSetV2", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// get system message
|
||||||
|
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0)
|
||||||
|
// apply message
|
||||||
|
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parlia) getValidatorElectionInfo(blockNr rpc.BlockNumberOrHash) ([]ValidatorItem, error) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
method := "getValidatorElectionInfo"
|
||||||
|
toAddress := common.HexToAddress(systemcontracts.StakeHubContract)
|
||||||
|
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
||||||
|
|
||||||
|
data, err := p.stakeHubABI.Pack(method, big.NewInt(0), big.NewInt(0))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to pack tx for getValidatorElectionInfo", "error", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
msgData := (hexutil.Bytes)(data)
|
||||||
|
|
||||||
|
result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||||
|
Gas: &gas,
|
||||||
|
To: &toAddress,
|
||||||
|
Data: &msgData,
|
||||||
|
}, blockNr, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var validators []common.Address
|
||||||
|
var votingPowers []*big.Int
|
||||||
|
var voteAddrs [][]byte
|
||||||
|
var totalLength *big.Int
|
||||||
|
if err := p.stakeHubABI.UnpackIntoInterface(&[]interface{}{&validators, &votingPowers, &voteAddrs, &totalLength}, method, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if totalLength.Int64() != int64(len(validators)) || totalLength.Int64() != int64(len(votingPowers)) || totalLength.Int64() != int64(len(voteAddrs)) {
|
||||||
|
return nil, fmt.Errorf("validator length not match")
|
||||||
|
}
|
||||||
|
|
||||||
|
validatorItems := make([]ValidatorItem, len(validators))
|
||||||
|
for i := 0; i < len(validators); i++ {
|
||||||
|
validatorItems[i] = ValidatorItem{
|
||||||
|
address: validators[i],
|
||||||
|
votingPower: votingPowers[i],
|
||||||
|
voteAddress: voteAddrs[i],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validatorItems, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parlia) getMaxElectedValidators(blockNr rpc.BlockNumberOrHash) (maxElectedValidators *big.Int, err error) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
method := "maxElectedValidators"
|
||||||
|
toAddress := common.HexToAddress(systemcontracts.StakeHubContract)
|
||||||
|
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
||||||
|
|
||||||
|
data, err := p.stakeHubABI.Pack(method)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to pack tx for maxElectedValidators", "error", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
msgData := (hexutil.Bytes)(data)
|
||||||
|
|
||||||
|
result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||||
|
Gas: &gas,
|
||||||
|
To: &toAddress,
|
||||||
|
Data: &msgData,
|
||||||
|
}, blockNr, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.stakeHubABI.UnpackIntoInterface(&maxElectedValidators, method, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxElectedValidators, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTopValidatorsByVotingPower(validatorItems []ValidatorItem, maxElectedValidators *big.Int) ([]common.Address, []uint64, [][]byte) {
|
||||||
|
var validatorHeap ValidatorHeap
|
||||||
|
for i := 0; i < len(validatorItems); i++ {
|
||||||
|
// only keep validators with voting power > 0
|
||||||
|
if validatorItems[i].votingPower.Cmp(big.NewInt(0)) == 1 {
|
||||||
|
validatorHeap = append(validatorHeap, validatorItems[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hp := &validatorHeap
|
||||||
|
heap.Init(hp)
|
||||||
|
|
||||||
|
topN := int(maxElectedValidators.Int64())
|
||||||
|
if topN > len(validatorHeap) {
|
||||||
|
topN = len(validatorHeap)
|
||||||
|
}
|
||||||
|
eValidators := make([]common.Address, topN)
|
||||||
|
eVotingPowers := make([]uint64, topN)
|
||||||
|
eVoteAddrs := make([][]byte, topN)
|
||||||
|
for i := 0; i < topN; i++ {
|
||||||
|
item := heap.Pop(hp).(ValidatorItem)
|
||||||
|
eValidators[i] = item.address
|
||||||
|
// as the decimal in BNB Beacon Chain is 1e8 and in BNB Smart Chain is 1e18, we need to divide it by 1e10
|
||||||
|
eVotingPowers[i] = new(big.Int).Div(item.votingPower, big.NewInt(1e10)).Uint64()
|
||||||
|
eVoteAddrs[i] = item.voteAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
return eValidators, eVotingPowers, eVoteAddrs
|
||||||
|
}
|
||||||
166
consensus/parlia/feynmanfork_test.go
Normal file
166
consensus/parlia/feynmanfork_test.go
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
package parlia
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidatorHeap(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
k int64
|
||||||
|
validators []ValidatorItem
|
||||||
|
expected []common.Address
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "normal case",
|
||||||
|
k: 2,
|
||||||
|
validators: []ValidatorItem{
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x1"),
|
||||||
|
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
|
||||||
|
voteAddress: []byte("0x1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x2"),
|
||||||
|
votingPower: new(big.Int).Mul(big.NewInt(200), big.NewInt(1e10)),
|
||||||
|
voteAddress: []byte("0x2"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x3"),
|
||||||
|
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
|
||||||
|
voteAddress: []byte("0x3"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: []common.Address{
|
||||||
|
common.HexToAddress("0x1"),
|
||||||
|
common.HexToAddress("0x2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "same voting power",
|
||||||
|
k: 2,
|
||||||
|
validators: []ValidatorItem{
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x1"),
|
||||||
|
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
|
||||||
|
voteAddress: []byte("0x1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x2"),
|
||||||
|
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
|
||||||
|
voteAddress: []byte("0x2"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x3"),
|
||||||
|
votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
|
||||||
|
voteAddress: []byte("0x3"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: []common.Address{
|
||||||
|
common.HexToAddress("0x1"),
|
||||||
|
common.HexToAddress("0x2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "zero voting power and k > len(validators)",
|
||||||
|
k: 5,
|
||||||
|
validators: []ValidatorItem{
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x1"),
|
||||||
|
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
|
||||||
|
voteAddress: []byte("0x1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x2"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x2"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x3"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x3"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x4"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x4"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: []common.Address{
|
||||||
|
common.HexToAddress("0x1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "zero voting power and k < len(validators)",
|
||||||
|
k: 2,
|
||||||
|
validators: []ValidatorItem{
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x1"),
|
||||||
|
votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
|
||||||
|
voteAddress: []byte("0x1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x2"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x2"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x3"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x3"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x4"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x4"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: []common.Address{
|
||||||
|
common.HexToAddress("0x1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "all zero voting power",
|
||||||
|
k: 2,
|
||||||
|
validators: []ValidatorItem{
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x1"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x2"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x2"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x3"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x3"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: common.HexToAddress("0x4"),
|
||||||
|
votingPower: big.NewInt(0),
|
||||||
|
voteAddress: []byte("0x4"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: []common.Address{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
eligibleValidators, _, _ := getTopValidatorsByVotingPower(tc.validators, big.NewInt(tc.k))
|
||||||
|
|
||||||
|
// check
|
||||||
|
if len(eligibleValidators) != len(tc.expected) {
|
||||||
|
t.Errorf("expected %d, got %d", len(tc.expected), len(eligibleValidators))
|
||||||
|
}
|
||||||
|
for i := 0; i < len(tc.expected); i++ {
|
||||||
|
if eligibleValidators[i] != tc.expected[i] {
|
||||||
|
t.Errorf("expected %s, got %s", tc.expected[i].Hex(), eligibleValidators[i].Hex())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -91,6 +90,10 @@ var (
|
|||||||
common.HexToAddress(systemcontracts.TokenHubContract): true,
|
common.HexToAddress(systemcontracts.TokenHubContract): true,
|
||||||
common.HexToAddress(systemcontracts.RelayerIncentivizeContract): true,
|
common.HexToAddress(systemcontracts.RelayerIncentivizeContract): true,
|
||||||
common.HexToAddress(systemcontracts.CrossChainContract): true,
|
common.HexToAddress(systemcontracts.CrossChainContract): true,
|
||||||
|
common.HexToAddress(systemcontracts.StakeHubContract): true,
|
||||||
|
common.HexToAddress(systemcontracts.GovernorContract): true,
|
||||||
|
common.HexToAddress(systemcontracts.GovTokenContract): true,
|
||||||
|
common.HexToAddress(systemcontracts.TimelockContract): true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -180,7 +183,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (
|
|||||||
signature := header.Extra[len(header.Extra)-extraSeal:]
|
signature := header.Extra[len(header.Extra)-extraSeal:]
|
||||||
|
|
||||||
// Recover the public key and the Ethereum address
|
// Recover the public key and the Ethereum address
|
||||||
pubkey, err := crypto.Ecrecover(SealHash(header, chainId).Bytes(), signature)
|
pubkey, err := crypto.Ecrecover(types.SealHash(header, chainId).Bytes(), signature)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
}
|
}
|
||||||
@@ -200,7 +203,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (
|
|||||||
// or not), which could be abused to produce different hashes for the same header.
|
// or not), which could be abused to produce different hashes for the same header.
|
||||||
func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
|
func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
encodeSigHeader(b, header, chainId)
|
types.EncodeSigHeader(b, header, chainId)
|
||||||
return b.Bytes()
|
return b.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +230,7 @@ type Parlia struct {
|
|||||||
validatorSetABIBeforeLuban abi.ABI
|
validatorSetABIBeforeLuban abi.ABI
|
||||||
validatorSetABI abi.ABI
|
validatorSetABI abi.ABI
|
||||||
slashABI abi.ABI
|
slashABI abi.ABI
|
||||||
|
stakeHubABI abi.ABI
|
||||||
|
|
||||||
// The fields below are for testing only
|
// The fields below are for testing only
|
||||||
fakeDiff bool // Skip difficulty verifications
|
fakeDiff bool // Skip difficulty verifications
|
||||||
@@ -269,6 +273,10 @@ func New(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
stABI, err := abi.JSON(strings.NewReader(stakeABI))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
c := &Parlia{
|
c := &Parlia{
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
config: parliaConfig,
|
config: parliaConfig,
|
||||||
@@ -280,6 +288,7 @@ func New(
|
|||||||
validatorSetABIBeforeLuban: vABIBeforeLuban,
|
validatorSetABIBeforeLuban: vABIBeforeLuban,
|
||||||
validatorSetABI: vABI,
|
validatorSetABI: vABI,
|
||||||
slashABI: sABI,
|
slashABI: sABI,
|
||||||
|
stakeHubABI: stABI,
|
||||||
signer: types.LatestSigner(chainConfig),
|
signer: types.LatestSigner(chainConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,7 +917,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
|
|||||||
// Prepare vote address bitset.
|
// Prepare vote address bitset.
|
||||||
for _, valInfo := range snap.Validators {
|
for _, valInfo := range snap.Validators {
|
||||||
if _, ok := voteAddrSet[valInfo.VoteAddress]; ok {
|
if _, ok := voteAddrSet[valInfo.VoteAddress]; ok {
|
||||||
attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) //Index is offset by 1
|
attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) // Index is offset by 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validatorsBitSet := bitset.From([]uint64{uint64(attestation.VoteAddressSet)})
|
validatorsBitSet := bitset.From([]uint64{uint64(attestation.VoteAddressSet)})
|
||||||
@@ -1158,6 +1167,31 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent := chain.GetHeaderByHash(header.ParentHash)
|
||||||
|
if parent == nil {
|
||||||
|
return errors.New("parent not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("!!! DEBUG Finalize block time", "number", header.Number, "time", header.Time, "parent time", parent.Time)
|
||||||
|
if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
|
||||||
|
err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("init feynman contract failed", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update validators every day
|
||||||
|
if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
|
||||||
|
// we should avoid update validators in the Feynman upgrade block
|
||||||
|
if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
|
||||||
|
if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(*systemTxs) > 0 {
|
if len(*systemTxs) > 0 {
|
||||||
return errors.New("the length of systemTxs do not match")
|
return errors.New("the length of systemTxs do not match")
|
||||||
}
|
}
|
||||||
@@ -1211,15 +1245,41 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
|
|||||||
|
|
||||||
err := p.distributeIncoming(p.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
|
err := p.distributeIncoming(p.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("p.distributeIncoming failed", "err", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.chainConfig.IsPlato(header.Number) {
|
if p.chainConfig.IsPlato(header.Number) {
|
||||||
if err := p.distributeFinalityReward(chain, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil {
|
if err := p.distributeFinalityReward(chain, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil {
|
||||||
|
log.Error("p.p.distributeFinalityReward after Plato failed", "err", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent := chain.GetHeaderByHash(header.ParentHash)
|
||||||
|
if parent == nil {
|
||||||
|
return nil, nil, errors.New("parent not found")
|
||||||
|
}
|
||||||
|
log.Info("!!! DEBUG FinalizeAndAssemble block time", "number", header.Number, "time", header.Time, "parent time", parent.Time)
|
||||||
|
if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
|
||||||
|
err := p.initializeFeynmanContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("init feynman contract failed", "error", err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update validators every day
|
||||||
|
if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
|
||||||
|
// we should avoid update validators in the Feynman upgrade block
|
||||||
|
if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
|
||||||
|
if err := p.updateValidatorSetV2(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil {
|
||||||
|
log.Error("p.updateValidatorSetV2 after Feynman failed", "err", err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// should not happen. Once happen, stop the node is better than broadcast the block
|
// should not happen. Once happen, stop the node is better than broadcast the block
|
||||||
if header.GasLimit < header.GasUsed {
|
if header.GasLimit < header.GasUsed {
|
||||||
return nil, nil, errors.New("gas consumption of system txs exceed the gas limit")
|
return nil, nil, errors.New("gas consumption of system txs exceed the gas limit")
|
||||||
@@ -1422,7 +1482,7 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res
|
|||||||
select {
|
select {
|
||||||
case results <- block.WithSeal(header):
|
case results <- block.WithSeal(header):
|
||||||
default:
|
default:
|
||||||
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID))
|
log.Warn("Sealing result is not read by miner", "sealhash", types.SealHash(header, p.chainConfig.ChainID))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -1496,7 +1556,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
|
|||||||
// So it's not the real hash of a block, just used as unique id to distinguish task
|
// So it's not the real hash of a block, just used as unique id to distinguish task
|
||||||
func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) {
|
func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) {
|
||||||
hasher := sha3.NewLegacyKeccak256()
|
hasher := sha3.NewLegacyKeccak256()
|
||||||
encodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
|
types.EncodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
|
||||||
hasher.Sum(hash[:0])
|
hasher.Sum(hash[:0])
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
@@ -1554,16 +1614,15 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNum *big.Int)
|
|||||||
|
|
||||||
var valSet []common.Address
|
var valSet []common.Address
|
||||||
var voteAddrSet []types.BLSPublicKey
|
var voteAddrSet []types.BLSPublicKey
|
||||||
|
|
||||||
if err := p.validatorSetABI.UnpackIntoInterface(&[]interface{}{&valSet, &voteAddrSet}, method, result); err != nil {
|
if err := p.validatorSetABI.UnpackIntoInterface(&[]interface{}{&valSet, &voteAddrSet}, method, result); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
voteAddrmap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
|
voteAddrMap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
|
||||||
for i := 0; i < len(valSet); i++ {
|
for i := 0; i < len(valSet); i++ {
|
||||||
voteAddrmap[valSet[i]] = &(voteAddrSet)[i]
|
voteAddrMap[valSet[i]] = &(voteAddrSet)[i]
|
||||||
}
|
}
|
||||||
return valSet, voteAddrmap, nil
|
return valSet, voteAddrMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// slash spoiled validators
|
// slash spoiled validators
|
||||||
@@ -1580,7 +1639,7 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he
|
|||||||
doDistributeSysReward := !p.chainConfig.IsKepler(header.Number, header.Time) &&
|
doDistributeSysReward := !p.chainConfig.IsKepler(header.Number, header.Time) &&
|
||||||
state.GetBalance(common.HexToAddress(systemcontracts.SystemRewardContract)).Cmp(maxSystemBalance) < 0
|
state.GetBalance(common.HexToAddress(systemcontracts.SystemRewardContract)).Cmp(maxSystemBalance) < 0
|
||||||
if doDistributeSysReward {
|
if doDistributeSysReward {
|
||||||
var rewards = new(big.Int)
|
rewards := new(big.Int)
|
||||||
rewards = rewards.Rsh(balance, systemRewardPercent)
|
rewards = rewards.Rsh(balance, systemRewardPercent)
|
||||||
if rewards.Cmp(common.Big0) > 0 {
|
if rewards.Cmp(common.Big0) > 0 {
|
||||||
err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||||
@@ -1802,62 +1861,6 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// =========================== utility function ==========================
|
// =========================== utility function ==========================
|
||||||
// SealHash returns the hash of a block prior to it being sealed.
|
|
||||||
func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) {
|
|
||||||
hasher := sha3.NewLegacyKeccak256()
|
|
||||||
encodeSigHeader(hasher, header, chainId)
|
|
||||||
hasher.Sum(hash[:0])
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
|
|
||||||
err := rlp.Encode(w, []interface{}{
|
|
||||||
chainId,
|
|
||||||
header.ParentHash,
|
|
||||||
header.UncleHash,
|
|
||||||
header.Coinbase,
|
|
||||||
header.Root,
|
|
||||||
header.TxHash,
|
|
||||||
header.ReceiptHash,
|
|
||||||
header.Bloom,
|
|
||||||
header.Difficulty,
|
|
||||||
header.Number,
|
|
||||||
header.GasLimit,
|
|
||||||
header.GasUsed,
|
|
||||||
header.Time,
|
|
||||||
header.Extra[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader
|
|
||||||
header.MixDigest,
|
|
||||||
header.Nonce,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic("can't encode: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeSigHeaderWithoutVoteAttestation(w io.Writer, header *types.Header, chainId *big.Int) {
|
|
||||||
err := rlp.Encode(w, []interface{}{
|
|
||||||
chainId,
|
|
||||||
header.ParentHash,
|
|
||||||
header.UncleHash,
|
|
||||||
header.Coinbase,
|
|
||||||
header.Root,
|
|
||||||
header.TxHash,
|
|
||||||
header.ReceiptHash,
|
|
||||||
header.Bloom,
|
|
||||||
header.Difficulty,
|
|
||||||
header.Number,
|
|
||||||
header.GasLimit,
|
|
||||||
header.GasUsed,
|
|
||||||
header.Time,
|
|
||||||
header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
|
|
||||||
header.MixDigest,
|
|
||||||
header.Nonce,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic("can't encode: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 {
|
func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 {
|
||||||
if snap.inturn(val) {
|
if snap.inturn(val) {
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import (
|
|||||||
"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/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -134,6 +135,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||||
err := p.engine.Finalize(p.bc, header, statedb, &commonTxs, block.Uncles(), withdrawals, &receipts, &systemTxs, usedGas)
|
err := p.engine.Finalize(p.bc, header, statedb, &commonTxs, block.Uncles(), withdrawals, &receipts, &systemTxs, usedGas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("!!!DEBUG!!! Failed to p.engine.Finalize block", "err", err)
|
||||||
return statedb, receipts, allLogs, *usedGas, err
|
return statedb, receipts, allLogs, *usedGas, err
|
||||||
}
|
}
|
||||||
for _, receipt := range receipts {
|
for _, receipt := range receipts {
|
||||||
|
|||||||
@@ -13,4 +13,10 @@ const (
|
|||||||
TokenManagerContract = "0x0000000000000000000000000000000000001008"
|
TokenManagerContract = "0x0000000000000000000000000000000000001008"
|
||||||
CrossChainContract = "0x0000000000000000000000000000000000002000"
|
CrossChainContract = "0x0000000000000000000000000000000000002000"
|
||||||
StakingContract = "0x0000000000000000000000000000000000002001"
|
StakingContract = "0x0000000000000000000000000000000000002001"
|
||||||
|
StakeHubContract = "0x0000000000000000000000000000000000002002"
|
||||||
|
StakeCreditContract = "0x0000000000000000000000000000000000002003"
|
||||||
|
GovernorContract = "0x0000000000000000000000000000000000002004"
|
||||||
|
GovTokenContract = "0x0000000000000000000000000000000000002005"
|
||||||
|
TimelockContract = "0x0000000000000000000000000000000000002006"
|
||||||
|
TokenRecoverPortalContract = "0x0000000000000000000000000000000000003000"
|
||||||
)
|
)
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -26,6 +26,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/sha3"
|
||||||
|
|
||||||
"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/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
@@ -560,8 +562,7 @@ func (d *DiffLayer) DecodeRLP(s *rlp.Stream) error {
|
|||||||
if err := s.Decode(&ed); err != nil {
|
if err := s.Decode(&ed); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
d.BlockHash, d.Number, d.Codes, d.Destructs, d.Accounts, d.Storages =
|
d.BlockHash, d.Number, d.Codes, d.Destructs, d.Accounts, d.Storages = ed.BlockHash, ed.Number, ed.Codes, ed.Destructs, ed.Accounts, ed.Storages
|
||||||
ed.BlockHash, ed.Number, ed.Codes, ed.Destructs, ed.Accounts, ed.Storages
|
|
||||||
|
|
||||||
d.Receipts = make([]*Receipt, len(ed.Receipts))
|
d.Receipts = make([]*Receipt, len(ed.Receipts))
|
||||||
for i, storageReceipt := range ed.Receipts {
|
for i, storageReceipt := range ed.Receipts {
|
||||||
@@ -608,6 +609,7 @@ func (storage *DiffStorage) Swap(i, j int) {
|
|||||||
storage.Keys[i], storage.Keys[j] = storage.Keys[j], storage.Keys[i]
|
storage.Keys[i], storage.Keys[j] = storage.Keys[j], storage.Keys[i]
|
||||||
storage.Vals[i], storage.Vals[j] = storage.Vals[j], storage.Vals[i]
|
storage.Vals[i], storage.Vals[j] = storage.Vals[j], storage.Vals[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (storage *DiffStorage) Less(i, j int) bool {
|
func (storage *DiffStorage) Less(i, j int) bool {
|
||||||
return string(storage.Keys[i][:]) < string(storage.Keys[j][:])
|
return string(storage.Keys[i][:]) < string(storage.Keys[j][:])
|
||||||
}
|
}
|
||||||
@@ -622,3 +624,64 @@ type DiffAccountsInBlock struct {
|
|||||||
BlockHash common.Hash
|
BlockHash common.Hash
|
||||||
Transactions []DiffAccountsInTx
|
Transactions []DiffAccountsInTx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
|
||||||
|
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
||||||
|
)
|
||||||
|
|
||||||
|
// SealHash returns the hash of a block prior to it being sealed.
|
||||||
|
func SealHash(header *Header, chainId *big.Int) (hash common.Hash) {
|
||||||
|
hasher := sha3.NewLegacyKeccak256()
|
||||||
|
EncodeSigHeader(hasher, header, chainId)
|
||||||
|
hasher.Sum(hash[:0])
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) {
|
||||||
|
err := rlp.Encode(w, []interface{}{
|
||||||
|
chainId,
|
||||||
|
header.ParentHash,
|
||||||
|
header.UncleHash,
|
||||||
|
header.Coinbase,
|
||||||
|
header.Root,
|
||||||
|
header.TxHash,
|
||||||
|
header.ReceiptHash,
|
||||||
|
header.Bloom,
|
||||||
|
header.Difficulty,
|
||||||
|
header.Number,
|
||||||
|
header.GasLimit,
|
||||||
|
header.GasUsed,
|
||||||
|
header.Time,
|
||||||
|
header.Extra[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader
|
||||||
|
header.MixDigest,
|
||||||
|
header.Nonce,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic("can't encode: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodeSigHeaderWithoutVoteAttestation(w io.Writer, header *Header, chainId *big.Int) {
|
||||||
|
err := rlp.Encode(w, []interface{}{
|
||||||
|
chainId,
|
||||||
|
header.ParentHash,
|
||||||
|
header.UncleHash,
|
||||||
|
header.Coinbase,
|
||||||
|
header.Root,
|
||||||
|
header.TxHash,
|
||||||
|
header.ReceiptHash,
|
||||||
|
header.Bloom,
|
||||||
|
header.Difficulty,
|
||||||
|
header.Number,
|
||||||
|
header.GasLimit,
|
||||||
|
header.GasUsed,
|
||||||
|
header.Time,
|
||||||
|
header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
|
||||||
|
header.MixDigest,
|
||||||
|
header.Nonce,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic("can't encode: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,23 +17,28 @@
|
|||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
||||||
|
"golang.org/x/crypto/ripemd160"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/blake2b"
|
"github.com/ethereum/go-ethereum/crypto/blake2b"
|
||||||
"github.com/ethereum/go-ethereum/crypto/bls12381"
|
"github.com/ethereum/go-ethereum/crypto/bls12381"
|
||||||
"github.com/ethereum/go-ethereum/crypto/bn256"
|
"github.com/ethereum/go-ethereum/crypto/bn256"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||||
"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/prysmaticlabs/prysm/v4/crypto/bls"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"golang.org/x/crypto/ripemd160"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrecompiledContract is the basic interface for native Go contracts. The implementation
|
// PrecompiledContract is the basic interface for native Go contracts. The implementation
|
||||||
@@ -219,6 +224,27 @@ var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
|
|||||||
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{},
|
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrecompiledContractsFeynman contains the default set of pre-compiled Ethereum
|
||||||
|
// contracts used in the Feynman release.
|
||||||
|
var PrecompiledContractsFeynman = map[common.Address]PrecompiledContract{
|
||||||
|
common.BytesToAddress([]byte{1}): &ecrecover{},
|
||||||
|
common.BytesToAddress([]byte{2}): &sha256hash{},
|
||||||
|
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
||||||
|
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||||
|
common.BytesToAddress([]byte{5}): &bigModExp{},
|
||||||
|
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
||||||
|
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||||
|
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||||
|
common.BytesToAddress([]byte{9}): &blake2F{},
|
||||||
|
|
||||||
|
common.BytesToAddress([]byte{100}): &tmHeaderValidate{},
|
||||||
|
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
|
||||||
|
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
|
||||||
|
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{},
|
||||||
|
common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
|
||||||
|
common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
|
||||||
|
}
|
||||||
|
|
||||||
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
|
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
|
||||||
// contracts specified in EIP-2537. These are exported for testing purposes.
|
// contracts specified in EIP-2537. These are exported for testing purposes.
|
||||||
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
|
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
|
||||||
@@ -245,6 +271,7 @@ var (
|
|||||||
PrecompiledAddressesIstanbul []common.Address
|
PrecompiledAddressesIstanbul []common.Address
|
||||||
PrecompiledAddressesByzantium []common.Address
|
PrecompiledAddressesByzantium []common.Address
|
||||||
PrecompiledAddressesHomestead []common.Address
|
PrecompiledAddressesHomestead []common.Address
|
||||||
|
PrecompiledAddressesFeynman []common.Address
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -281,11 +308,16 @@ func init() {
|
|||||||
for k := range PrecompiledContractsCancun {
|
for k := range PrecompiledContractsCancun {
|
||||||
PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k)
|
PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k)
|
||||||
}
|
}
|
||||||
|
for k := range PrecompiledContractsFeynman {
|
||||||
|
PrecompiledAddressesFeynman = append(PrecompiledAddressesFeynman, k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActivePrecompiles returns the precompiles enabled with the current configuration.
|
// ActivePrecompiles returns the precompiles enabled with the current configuration.
|
||||||
func ActivePrecompiles(rules params.Rules) []common.Address {
|
func ActivePrecompiles(rules params.Rules) []common.Address {
|
||||||
switch {
|
switch {
|
||||||
|
case rules.IsFeynman:
|
||||||
|
return PrecompiledAddressesFeynman
|
||||||
case rules.IsCancun:
|
case rules.IsCancun:
|
||||||
return PrecompiledAddressesCancun
|
return PrecompiledAddressesCancun
|
||||||
case rules.IsHertz:
|
case rules.IsHertz:
|
||||||
@@ -561,7 +593,7 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
|
|||||||
// Modulo 0 is undefined, return zero
|
// Modulo 0 is undefined, return zero
|
||||||
return common.LeftPadBytes([]byte{}, int(modLen)), nil
|
return common.LeftPadBytes([]byte{}, int(modLen)), nil
|
||||||
case base.BitLen() == 1: // a bit length of 1 means it's 1 (or -1).
|
case base.BitLen() == 1: // a bit length of 1 means it's 1 (or -1).
|
||||||
//If base == 1, then we can just return base % mod (if mod >= 1, which it is)
|
// If base == 1, then we can just return base % mod (if mod >= 1, which it is)
|
||||||
v = base.Mod(base, mod).Bytes()
|
v = base.Mod(base, mod).Bytes()
|
||||||
default:
|
default:
|
||||||
v = base.Exp(base, exp, mod).Bytes()
|
v = base.Exp(base, exp, mod).Bytes()
|
||||||
@@ -1355,3 +1387,88 @@ func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash {
|
|||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verifyDoubleSignEvidence implements bsc header verification precompile.
|
||||||
|
type verifyDoubleSignEvidence struct{}
|
||||||
|
|
||||||
|
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||||
|
func (c *verifyDoubleSignEvidence) RequiredGas(input []byte) uint64 {
|
||||||
|
return params.DoubleSignEvidenceVerifyGas
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
extraSeal = 65
|
||||||
|
)
|
||||||
|
|
||||||
|
type DoubleSignEvidence struct {
|
||||||
|
ChainId *big.Int
|
||||||
|
HeaderBytes1 []byte
|
||||||
|
HeaderBytes2 []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run input: rlp encoded DoubleSignEvidence
|
||||||
|
// return:
|
||||||
|
// signer address| evidence height|
|
||||||
|
// 20 bytes | 32 bytes |
|
||||||
|
func (c *verifyDoubleSignEvidence) Run(input []byte) ([]byte, error) {
|
||||||
|
evidence := &DoubleSignEvidence{}
|
||||||
|
err := rlp.DecodeBytes(input, evidence)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
header1 := &types.Header{}
|
||||||
|
err = rlp.DecodeBytes(evidence.HeaderBytes1, header1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
header2 := &types.Header{}
|
||||||
|
err = rlp.DecodeBytes(evidence.HeaderBytes2, header2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
// basic check
|
||||||
|
if header1.Number.Cmp(header2.Number) != 0 {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
if header1.ParentHash != header2.ParentHash {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(header1.Extra) < extraSeal || len(header2.Extra) < extraSeal {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
sig1 := header1.Extra[len(header1.Extra)-extraSeal:]
|
||||||
|
sig2 := header2.Extra[len(header2.Extra)-extraSeal:]
|
||||||
|
if bytes.Equal(sig1, sig2) {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
// check sig
|
||||||
|
msgHash1 := types.SealHash(header1, evidence.ChainId)
|
||||||
|
msgHash2 := types.SealHash(header2, evidence.ChainId)
|
||||||
|
if bytes.Equal(msgHash1.Bytes(), msgHash2.Bytes()) {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
pubkey1, err := secp256k1.RecoverPubkey(msgHash1.Bytes(), sig1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
pubkey2, err := secp256k1.RecoverPubkey(msgHash2.Bytes(), sig2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
if !bytes.Equal(pubkey1, pubkey2) {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
returnBz := make([]byte, 52) // 20 + 32
|
||||||
|
signerAddr := crypto.Keccak256(pubkey1[1:])[12:]
|
||||||
|
evidenceHeightBz := header1.Number.Bytes()
|
||||||
|
copy(returnBz[:20], signerAddr)
|
||||||
|
copy(returnBz[52-len(evidenceHeightBz):], evidenceHeightBz)
|
||||||
|
|
||||||
|
return returnBz, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ import (
|
|||||||
|
|
||||||
"github.com/tendermint/iavl"
|
"github.com/tendermint/iavl"
|
||||||
"github.com/tendermint/tendermint/crypto/merkle"
|
"github.com/tendermint/tendermint/crypto/merkle"
|
||||||
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
|
|
||||||
|
//nolint:staticcheck
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
v1 "github.com/ethereum/go-ethereum/core/vm/lightclient/v1"
|
v1 "github.com/ethereum/go-ethereum/core/vm/lightclient/v1"
|
||||||
v2 "github.com/ethereum/go-ethereum/core/vm/lightclient/v2"
|
v2 "github.com/ethereum/go-ethereum/core/vm/lightclient/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -104,7 +108,7 @@ func (c *tmHeaderValidate) Run(input []byte) (result []byte, err error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// iavlMerkleProofValidate implemented as a native contract.
|
// iavlMerkleProofValidate implemented as a native contract.
|
||||||
type iavlMerkleProofValidate struct {
|
type iavlMerkleProofValidate struct {
|
||||||
@@ -397,3 +401,43 @@ type cometBFTLightBlockValidateHertz struct {
|
|||||||
func (c *cometBFTLightBlockValidateHertz) Run(input []byte) (result []byte, err error) {
|
func (c *cometBFTLightBlockValidateHertz) Run(input []byte) (result []byte, err error) {
|
||||||
return c.run(input, true)
|
return c.run(input, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// secp256k1SignatureRecover implemented as a native contract.
|
||||||
|
type secp256k1SignatureRecover struct{}
|
||||||
|
|
||||||
|
func (c *secp256k1SignatureRecover) RequiredGas(input []byte) uint64 {
|
||||||
|
return params.EcrecoverGas
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
tmPubKeyLength uint8 = 33
|
||||||
|
tmSignatureLength uint8 = 64
|
||||||
|
tmSignatureMsgHashLength uint8 = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
// input:
|
||||||
|
// | tmPubKey | tmSignature | tmSignatureMsgHash |
|
||||||
|
// | 33 bytes | 64 bytes | 32 bytes |
|
||||||
|
func (c *secp256k1SignatureRecover) Run(input []byte) (result []byte, err error) {
|
||||||
|
if len(input) != int(tmPubKeyLength)+int(tmSignatureLength)+int(tmSignatureMsgHashLength) {
|
||||||
|
return nil, fmt.Errorf("invalid input")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warn("!!!DEBUG!! secp256k1SignatureRecover", "input", hexutil.Encode(input))
|
||||||
|
return c.runTMSecp256k1Signature(
|
||||||
|
input[:tmPubKeyLength],
|
||||||
|
input[tmPubKeyLength:tmPubKeyLength+tmSignatureLength],
|
||||||
|
input[tmPubKeyLength+tmSignatureLength:],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *secp256k1SignatureRecover) runTMSecp256k1Signature(pubkey, signatureStr, msgHash []byte) (result []byte, err error) {
|
||||||
|
tmPubKey := secp256k1.PubKeySecp256k1(pubkey)
|
||||||
|
ok := tmPubKey.VerifyBytesWithMsgHash(msgHash, signatureStr)
|
||||||
|
log.Warn("!!!DEBUG!! secp256k1SignatureRecover", "ok", ok)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid signature")
|
||||||
|
}
|
||||||
|
log.Warn("!!!DEBUG!! secp256k1SignatureRecover", "address", hexutil.Encode(tmPubKey.Address().Bytes()))
|
||||||
|
return tmPubKey.Address().Bytes(), nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -373,3 +373,42 @@ func TestCometBFTLightBlockValidateHertz(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, expectOutputStr, hex.EncodeToString(res))
|
require.Equal(t, expectOutputStr, hex.EncodeToString(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSecp256k1SignatureRecover(t *testing.T) {
|
||||||
|
// local key
|
||||||
|
{
|
||||||
|
pubKey, err := hex.DecodeString("0278caa4d6321aa856d6341dd3e8bcdfe0b55901548871c63c3f5cec43c2ae88a9")
|
||||||
|
require.NoError(t, err)
|
||||||
|
sig, err := hex.DecodeString("0cb78be0d8eaeab991907b06c61240c04f4ca83f54b7799ce77cf029b837988038c4b3b7f5df231695b0d14499b716e1fd6504860eb3c9244ecb4e569d44c062")
|
||||||
|
require.NoError(t, err)
|
||||||
|
msghash, err := hex.DecodeString("b6ac827edff4bbbf23579720782dbef40b65780af292cc66849e7e5944f1230f")
|
||||||
|
require.NoError(t, err)
|
||||||
|
expectedAddr, err := hex.DecodeString("fa3B227adFf8EA1706098928715076D76959Ae6c")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
input := append(append(pubKey, sig...), msghash...)
|
||||||
|
contract := &secp256k1SignatureRecover{}
|
||||||
|
res, err := contract.Run(input)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, expectedAddr, res)
|
||||||
|
}
|
||||||
|
// ledger
|
||||||
|
{
|
||||||
|
pubKey, err := hex.DecodeString("02d63ee39adb1779353b4393dd5ea9d6d2b6df63b71d168571803cc7b9a0a20e98")
|
||||||
|
require.NoError(t, err)
|
||||||
|
sig, err := hex.DecodeString("66bdb5d381b2773c0f569858c7ee143959522d7c1f46dc656c325cb7353ec40c28ec22dff3650b34c096c5b12e702d7237d409f1ebaaa6dd1128a8f2d401fd5b")
|
||||||
|
require.NoError(t, err)
|
||||||
|
msghash, err := hex.DecodeString("c45e8f0dc7c054c31912beeffd6f10f1c585606d61e252e97968cd66661c2571")
|
||||||
|
require.NoError(t, err)
|
||||||
|
expectedAddr, err := hex.DecodeString("65a284146b84210a01add088954bb52d88b230af")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
input := append(append(pubKey, sig...), msghash...)
|
||||||
|
contract := &secp256k1SignatureRecover{}
|
||||||
|
res, err := contract.Run(input)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, expectedAddr, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
|
|||||||
common.BytesToAddress([]byte{0x0f, 0x11}): &bls12381MapG1{},
|
common.BytesToAddress([]byte{0x0f, 0x11}): &bls12381MapG1{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x12}): &bls12381MapG2{},
|
common.BytesToAddress([]byte{0x0f, 0x12}): &bls12381MapG2{},
|
||||||
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
|
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
|
||||||
|
common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// EIP-152 test vectors
|
// EIP-152 test vectors
|
||||||
@@ -405,3 +406,14 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
|
|||||||
}
|
}
|
||||||
benchmarkPrecompiled("0f", testcase, b)
|
benchmarkPrecompiled("0f", testcase, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDoubleSignSlash(t *testing.T) {
|
||||||
|
tc := precompiledTest{
|
||||||
|
Input: "f906278202cab9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494976ea74026e726554db657fa54763abd0c3a0aa9a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a804ae755e0fe64b59753f4db6308a1f679747bce186aa2c62b95fa6eeff3fbd08f3b0667e45428a54ade15bad19f49641c499b431b36f65803ea71b379e6b61de501a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094976ea74026e726554db657fa54763abd0c3a0aa9a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a80c0b17bfe88534296ff064cb7156548f6deba2d6310d5044ed6485f087dc6ef232e051c28e1909c2b50a3b4f29345d66681c319bef653e52e5d746480d5a3983b00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000",
|
||||||
|
Expected: "15d34aaf54267db7d7c367839aaf71a00a2c6a650000000000000000000000000000000000000000000000000000000000000cdf",
|
||||||
|
Gas: 1000,
|
||||||
|
Name: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
testPrecompiled("68", tc, t)
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ type (
|
|||||||
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
||||||
var precompiles map[common.Address]PrecompiledContract
|
var precompiles map[common.Address]PrecompiledContract
|
||||||
switch {
|
switch {
|
||||||
|
case evm.chainRules.IsFeynman:
|
||||||
|
precompiles = PrecompiledContractsFeynman
|
||||||
case evm.chainRules.IsCancun:
|
case evm.chainRules.IsCancun:
|
||||||
precompiles = PrecompiledContractsCancun
|
precompiles = PrecompiledContractsCancun
|
||||||
case evm.chainRules.IsHertz:
|
case evm.chainRules.IsHertz:
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -295,5 +295,5 @@ replace (
|
|||||||
github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-tendermint v0.0.0-20230417032003-4cda1f296fb2
|
github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-tendermint v0.0.0-20230417032003-4cda1f296fb2
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 => github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1
|
github.com/grpc-ecosystem/grpc-gateway/v2 => github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1
|
||||||
github.com/syndtr/goleveldb v1.0.1 => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
github.com/syndtr/goleveldb v1.0.1 => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||||
github.com/tendermint/tendermint => github.com/bnb-chain/tendermint v0.31.15
|
github.com/tendermint/tendermint => github.com/bnb-chain/tendermint v0.31.16
|
||||||
)
|
)
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -188,8 +188,8 @@ github.com/bnb-chain/greenfield-tendermint v0.0.0-20230417032003-4cda1f296fb2 h1
|
|||||||
github.com/bnb-chain/greenfield-tendermint v0.0.0-20230417032003-4cda1f296fb2/go.mod h1:9q11eHNRY9FDwFH+4pompzPNGv//Z3VcfvkELaHJPMs=
|
github.com/bnb-chain/greenfield-tendermint v0.0.0-20230417032003-4cda1f296fb2/go.mod h1:9q11eHNRY9FDwFH+4pompzPNGv//Z3VcfvkELaHJPMs=
|
||||||
github.com/bnb-chain/ics23 v0.1.0 h1:DvjGOts2FBfbxB48384CYD1LbcrfjThFz8kowY/7KxU=
|
github.com/bnb-chain/ics23 v0.1.0 h1:DvjGOts2FBfbxB48384CYD1LbcrfjThFz8kowY/7KxU=
|
||||||
github.com/bnb-chain/ics23 v0.1.0/go.mod h1:cU6lTGolbbLFsGCgceNB2AzplH1xecLp6+KXvxM32nI=
|
github.com/bnb-chain/ics23 v0.1.0/go.mod h1:cU6lTGolbbLFsGCgceNB2AzplH1xecLp6+KXvxM32nI=
|
||||||
github.com/bnb-chain/tendermint v0.31.15 h1:Xyn/Hifb/7X4E1zSuMdnZdMSoM2Fx6cZuKCNnqIxbNU=
|
github.com/bnb-chain/tendermint v0.31.16 h1:rOO6WG61JDAuRCCL8TKnGhorJftQDVygq0mqR7A0ck4=
|
||||||
github.com/bnb-chain/tendermint v0.31.15/go.mod h1:cmt8HHmQUSVaWQ/hoTefRxsh5X3ERaM1zCUIR0DPbFU=
|
github.com/bnb-chain/tendermint v0.31.16/go.mod h1:cmt8HHmQUSVaWQ/hoTefRxsh5X3ERaM1zCUIR0DPbFU=
|
||||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||||
|
|||||||
@@ -711,10 +711,10 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
|
|||||||
gasLimit := env.header.GasLimit
|
gasLimit := env.header.GasLimit
|
||||||
if env.gasPool == nil {
|
if env.gasPool == nil {
|
||||||
env.gasPool = new(core.GasPool).AddGas(gasLimit)
|
env.gasPool = new(core.GasPool).AddGas(gasLimit)
|
||||||
if w.chain.Config().IsEuler(env.header.Number) {
|
if w.chain.Config().IsFeynman(env.header.Number, env.header.Time) {
|
||||||
env.gasPool.SubGas(params.SystemTxsGas * 3)
|
env.gasPool.SubGas(params.SystemTxsGas * 40) // 20,000,000
|
||||||
} else {
|
} else {
|
||||||
env.gasPool.SubGas(params.SystemTxsGas)
|
env.gasPool.SubGas(params.SystemTxsGas * 5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,7 +728,7 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
|
|||||||
|
|
||||||
stopPrefetchCh := make(chan struct{})
|
stopPrefetchCh := make(chan struct{})
|
||||||
defer close(stopPrefetchCh)
|
defer close(stopPrefetchCh)
|
||||||
//prefetch txs from all pending txs
|
// prefetch txs from all pending txs
|
||||||
txsPrefetch := txs.Copy()
|
txsPrefetch := txs.Copy()
|
||||||
tx := txsPrefetch.PeekWithUnwrap()
|
tx := txsPrefetch.PeekWithUnwrap()
|
||||||
if tx != nil {
|
if tx != nil {
|
||||||
@@ -974,6 +974,7 @@ func (w *worker) generateWork(params *generateParams) (*types.Block, *big.Int, e
|
|||||||
fees := work.state.GetBalance(consensus.SystemAddress)
|
fees := work.state.GetBalance(consensus.SystemAddress)
|
||||||
block, _, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, nil, work.receipts, params.withdrawals)
|
block, _, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, nil, work.receipts, params.withdrawals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("!!!DEBUG!!! Failed to assemble block in generateWork", "err", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return block, fees, nil
|
return block, fees, nil
|
||||||
@@ -1176,6 +1177,7 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti
|
|||||||
finalizeStart := time.Now()
|
finalizeStart := time.Now()
|
||||||
block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(env.header), env.state, env.txs, nil, env.receipts, nil)
|
block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(env.header), env.state, env.txs, nil, env.receipts, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("!!!DEBUG!!! Failed to assemble block in commit", "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// env.receipts = receipts
|
// env.receipts = receipts
|
||||||
|
|||||||
123
params/config.go
123
params/config.go
@@ -66,6 +66,27 @@ var (
|
|||||||
Ethash: new(EthashConfig),
|
Ethash: new(EthashConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// just for prysm compile pass
|
||||||
|
// RopstenChainConfig contains the chain parameters to run a node on the Ropsten test network.
|
||||||
|
RopstenChainConfig = &ChainConfig{
|
||||||
|
ChainID: big.NewInt(3),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
DAOForkBlock: nil,
|
||||||
|
DAOForkSupport: true,
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(10),
|
||||||
|
EIP158Block: big.NewInt(10),
|
||||||
|
ByzantiumBlock: big.NewInt(1_700_000),
|
||||||
|
ConstantinopleBlock: big.NewInt(4_230_000),
|
||||||
|
PetersburgBlock: big.NewInt(4_939_394),
|
||||||
|
IstanbulBlock: big.NewInt(6_485_846),
|
||||||
|
MuirGlacierBlock: big.NewInt(7_117_117),
|
||||||
|
BerlinBlock: big.NewInt(9_812_189),
|
||||||
|
LondonBlock: big.NewInt(10_499_401),
|
||||||
|
TerminalTotalDifficulty: new(big.Int).SetUint64(50_000_000_000_000_000),
|
||||||
|
Ethash: new(EthashConfig),
|
||||||
|
}
|
||||||
|
|
||||||
// just for prysm compile pass
|
// just for prysm compile pass
|
||||||
// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
|
// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
|
||||||
SepoliaChainConfig = &ChainConfig{
|
SepoliaChainConfig = &ChainConfig{
|
||||||
@@ -148,6 +169,9 @@ var (
|
|||||||
ShanghaiTime: newUint64(1705996800),
|
ShanghaiTime: newUint64(1705996800),
|
||||||
KeplerTime: newUint64(1705996800),
|
KeplerTime: newUint64(1705996800),
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
FeynmanTime: nil,
|
||||||
|
|
||||||
Parlia: &ParliaConfig{
|
Parlia: &ParliaConfig{
|
||||||
Period: 3,
|
Period: 3,
|
||||||
Epoch: 200,
|
Epoch: 200,
|
||||||
@@ -184,13 +208,15 @@ var (
|
|||||||
ShanghaiTime: newUint64(1702972800),
|
ShanghaiTime: newUint64(1702972800),
|
||||||
KeplerTime: newUint64(1702972800),
|
KeplerTime: newUint64(1702972800),
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
FeynmanTime: _rialto_upgrade_height_,
|
||||||
|
|
||||||
Parlia: &ParliaConfig{
|
Parlia: &ParliaConfig{
|
||||||
Period: 3,
|
Period: 3,
|
||||||
Epoch: 200,
|
Epoch: 200,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to test hard fork upgrade, following https://github.com/bnb-chain/bsc-genesis-contract/blob/master/genesis.json
|
|
||||||
RialtoChainConfig = &ChainConfig{
|
RialtoChainConfig = &ChainConfig{
|
||||||
ChainID: big.NewInt(714),
|
ChainID: big.NewInt(714),
|
||||||
HomesteadBlock: big.NewInt(0),
|
HomesteadBlock: big.NewInt(0),
|
||||||
@@ -207,9 +233,9 @@ var (
|
|||||||
MirrorSyncBlock: big.NewInt(1),
|
MirrorSyncBlock: big.NewInt(1),
|
||||||
BrunoBlock: big.NewInt(1),
|
BrunoBlock: big.NewInt(1),
|
||||||
EulerBlock: big.NewInt(2),
|
EulerBlock: big.NewInt(2),
|
||||||
NanoBlock: big.NewInt(3),
|
GibbsBlock: big.NewInt(3),
|
||||||
MoranBlock: big.NewInt(3),
|
NanoBlock: nil,
|
||||||
GibbsBlock: big.NewInt(4),
|
MoranBlock: big.NewInt(4),
|
||||||
PlanckBlock: big.NewInt(5),
|
PlanckBlock: big.NewInt(5),
|
||||||
LubanBlock: big.NewInt(6),
|
LubanBlock: big.NewInt(6),
|
||||||
PlatoBlock: big.NewInt(7),
|
PlatoBlock: big.NewInt(7),
|
||||||
@@ -217,12 +243,15 @@ var (
|
|||||||
LondonBlock: big.NewInt(8),
|
LondonBlock: big.NewInt(8),
|
||||||
HertzBlock: big.NewInt(8),
|
HertzBlock: big.NewInt(8),
|
||||||
HertzfixBlock: big.NewInt(8),
|
HertzfixBlock: big.NewInt(8),
|
||||||
ShanghaiTime: newUint64(0),
|
|
||||||
KeplerTime: newUint64(0),
|
// TODO
|
||||||
|
ShanghaiTime: _rialto_upgrade_height_,
|
||||||
|
KeplerTime: _rialto_upgrade_height_,
|
||||||
|
FeynmanTime: _rialto_upgrade_height_,
|
||||||
|
|
||||||
Parlia: &ParliaConfig{
|
Parlia: &ParliaConfig{
|
||||||
Period: 3,
|
Period: _rialto_parlia_period_,
|
||||||
Epoch: 200,
|
Epoch: _rialto_parlia_epoch_,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,10 +458,10 @@ var NetworkNames = map[string]string{
|
|||||||
type ChainConfig struct {
|
type ChainConfig struct {
|
||||||
ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
|
ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
|
||||||
|
|
||||||
HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead)
|
HomesteadBlock *big.Int `json:"homesteadBlock,omitempty" toml:",omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead)
|
||||||
|
|
||||||
DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` // TheDAO hard-fork switch block (nil = no fork)
|
DAOForkBlock *big.Int `json:"daoForkBlock,omitempty" toml:",omitempty"` // TheDAO hard-fork switch block (nil = no fork)
|
||||||
DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
|
DAOForkSupport bool `json:"daoForkSupport,omitempty" toml:",omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
|
||||||
|
|
||||||
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
|
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
|
||||||
EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
|
EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
|
||||||
@@ -454,11 +483,12 @@ type ChainConfig struct {
|
|||||||
|
|
||||||
// Fork scheduling was switched from blocks to timestamps here
|
// Fork scheduling was switched from blocks to timestamps here
|
||||||
|
|
||||||
ShanghaiTime *uint64 `json:"shanghaiTime,omitempty" ` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
|
ShanghaiTime *uint64 `json:"shanghaiTime,omitempty" toml:",omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
|
||||||
KeplerTime *uint64 `json:"keplerTime,omitempty"` // Kepler switch time (nil = no fork, 0 = already activated)
|
KeplerTime *uint64 `json:"keplerTime,omitempty" toml:",omitempty"` // Kepler switch time (nil = no fork, 0 = already activated)
|
||||||
CancunTime *uint64 `json:"cancunTime,omitempty" ` // Cancun switch time (nil = no fork, 0 = already on cancun)
|
FeynmanTime *uint64 `json:"feynmanTime,omitempty" toml:",omitempty"` // Feynman switch time (nil = no fork, 0 = already activated)
|
||||||
PragueTime *uint64 `json:"pragueTime,omitempty" ` // Prague switch time (nil = no fork, 0 = already on prague)
|
CancunTime *uint64 `json:"cancunTime,omitempty" toml:",omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun)
|
||||||
VerkleTime *uint64 `json:"verkleTime,omitempty" ` // Verkle switch time (nil = no fork, 0 = already on verkle)
|
PragueTime *uint64 `json:"pragueTime,omitempty" toml:",omitempty"` // Prague switch time (nil = no fork, 0 = already on prague)
|
||||||
|
VerkleTime *uint64 `json:"verkleTime,omitempty" toml:",omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle)
|
||||||
|
|
||||||
// TerminalTotalDifficulty is the amount of total difficulty reached by
|
// TerminalTotalDifficulty is the amount of total difficulty reached by
|
||||||
// the network that triggers the consensus upgrade.
|
// the network that triggers the consensus upgrade.
|
||||||
@@ -469,23 +499,23 @@ type ChainConfig struct {
|
|||||||
// even without having seen the TTD locally (safer long term).
|
// even without having seen the TTD locally (safer long term).
|
||||||
TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
|
TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
|
||||||
|
|
||||||
RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated)
|
RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty" toml:",omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated)
|
||||||
NielsBlock *big.Int `json:"nielsBlock,omitempty"` // nielsBlock switch block (nil = no fork, 0 = already activated)
|
NielsBlock *big.Int `json:"nielsBlock,omitempty" toml:",omitempty"` // nielsBlock switch block (nil = no fork, 0 = already activated)
|
||||||
MirrorSyncBlock *big.Int `json:"mirrorSyncBlock,omitempty"` // mirrorSyncBlock switch block (nil = no fork, 0 = already activated)
|
MirrorSyncBlock *big.Int `json:"mirrorSyncBlock,omitempty" toml:",omitempty"` // mirrorSyncBlock switch block (nil = no fork, 0 = already activated)
|
||||||
BrunoBlock *big.Int `json:"brunoBlock,omitempty"` // brunoBlock switch block (nil = no fork, 0 = already activated)
|
BrunoBlock *big.Int `json:"brunoBlock,omitempty" toml:",omitempty"` // brunoBlock switch block (nil = no fork, 0 = already activated)
|
||||||
EulerBlock *big.Int `json:"eulerBlock,omitempty"` // eulerBlock switch block (nil = no fork, 0 = already activated)
|
EulerBlock *big.Int `json:"eulerBlock,omitempty" toml:",omitempty"` // eulerBlock switch block (nil = no fork, 0 = already activated)
|
||||||
GibbsBlock *big.Int `json:"gibbsBlock,omitempty"` // gibbsBlock switch block (nil = no fork, 0 = already activated)
|
GibbsBlock *big.Int `json:"gibbsBlock,omitempty" toml:",omitempty"` // gibbsBlock switch block (nil = no fork, 0 = already activated)
|
||||||
NanoBlock *big.Int `json:"nanoBlock,omitempty"` // nanoBlock switch block (nil = no fork, 0 = already activated)
|
NanoBlock *big.Int `json:"nanoBlock,omitempty" toml:",omitempty"` // nanoBlock switch block (nil = no fork, 0 = already activated)
|
||||||
MoranBlock *big.Int `json:"moranBlock,omitempty"` // moranBlock switch block (nil = no fork, 0 = already activated)
|
MoranBlock *big.Int `json:"moranBlock,omitempty" toml:",omitempty"` // moranBlock switch block (nil = no fork, 0 = already activated)
|
||||||
PlanckBlock *big.Int `json:"planckBlock,omitempty"` // planckBlock switch block (nil = no fork, 0 = already activated)
|
PlanckBlock *big.Int `json:"planckBlock,omitempty" toml:",omitempty"` // planckBlock switch block (nil = no fork, 0 = already activated)
|
||||||
LubanBlock *big.Int `json:"lubanBlock,omitempty"` // lubanBlock switch block (nil = no fork, 0 = already activated)
|
LubanBlock *big.Int `json:"lubanBlock,omitempty" toml:",omitempty"` // lubanBlock switch block (nil = no fork, 0 = already activated)
|
||||||
PlatoBlock *big.Int `json:"platoBlock,omitempty"` // platoBlock switch block (nil = no fork, 0 = already activated)
|
PlatoBlock *big.Int `json:"platoBlock,omitempty" toml:",omitempty"` // platoBlock switch block (nil = no fork, 0 = already activated)
|
||||||
HertzBlock *big.Int `json:"hertzBlock,omitempty"` // hertzBlock switch block (nil = no fork, 0 = already activated)
|
HertzBlock *big.Int `json:"hertzBlock,omitempty" toml:",omitempty"` // hertzBlock switch block (nil = no fork, 0 = already activated)
|
||||||
HertzfixBlock *big.Int `json:"hertzfixBlock,omitempty"` // hertzfixBlock switch block (nil = no fork, 0 = already activated)
|
HertzfixBlock *big.Int `json:"hertzfixBlock,omitempty" toml:",omitempty"` // hertzfixBlock switch block (nil = no fork, 0 = already activated)
|
||||||
// Various consensus engines
|
// Various consensus engines
|
||||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
Ethash *EthashConfig `json:"ethash,omitempty" toml:",omitempty"`
|
||||||
Clique *CliqueConfig `json:"clique,omitempty"`
|
Clique *CliqueConfig `json:"clique,omitempty" toml:",omitempty"`
|
||||||
Parlia *ParliaConfig `json:"parlia,omitempty"`
|
Parlia *ParliaConfig `json:"parlia,omitempty" toml:",omitempty"`
|
||||||
IsDevMode bool `json:"isDev,omitempty"`
|
IsDevMode bool `json:"isDev,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,7 +578,12 @@ func (c *ChainConfig) String() string {
|
|||||||
KeplerTime = big.NewInt(0).SetUint64(*c.KeplerTime)
|
KeplerTime = big.NewInt(0).SetUint64(*c.KeplerTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Hertz: %v, Hertzfix: %v, ShanghaiTime: %v, KeplerTime: %v, Engine: %v}",
|
var FeynmanTime *big.Int
|
||||||
|
if c.FeynmanTime != nil {
|
||||||
|
FeynmanTime = big.NewInt(0).SetUint64(*c.FeynmanTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Hertz: %v, Hertzfix: %v, ShanghaiTime: %v, KeplerTime: %v, FeynmanTime: %v, Engine: %v}",
|
||||||
c.ChainID,
|
c.ChainID,
|
||||||
c.HomesteadBlock,
|
c.HomesteadBlock,
|
||||||
c.DAOForkBlock,
|
c.DAOForkBlock,
|
||||||
@@ -582,6 +617,7 @@ func (c *ChainConfig) String() string {
|
|||||||
c.HertzfixBlock,
|
c.HertzfixBlock,
|
||||||
ShanghaiTime,
|
ShanghaiTime,
|
||||||
KeplerTime,
|
KeplerTime,
|
||||||
|
FeynmanTime,
|
||||||
engine,
|
engine,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -816,6 +852,20 @@ func (c *ChainConfig) IsOnKepler(currentBlockNumber *big.Int, lastBlockTime uint
|
|||||||
return !c.IsKepler(lastBlockNumber, lastBlockTime) && c.IsKepler(currentBlockNumber, currentBlockTime)
|
return !c.IsKepler(lastBlockNumber, lastBlockTime) && c.IsKepler(currentBlockNumber, currentBlockTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsFeynman returns whether time is either equal to the Feynman fork time or greater.
|
||||||
|
func (c *ChainConfig) IsFeynman(num *big.Int, time uint64) bool {
|
||||||
|
return c.IsLondon(num) && isTimestampForked(c.FeynmanTime, time)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOnFeynman returns whether currentBlockTime is either equal to the Feynman fork time or greater firstly.
|
||||||
|
func (c *ChainConfig) IsOnFeynman(currentBlockNumber *big.Int, lastBlockTime uint64, currentBlockTime uint64) bool {
|
||||||
|
lastBlockNumber := new(big.Int)
|
||||||
|
if currentBlockNumber.Cmp(big.NewInt(1)) >= 0 {
|
||||||
|
lastBlockNumber.Sub(currentBlockNumber, big.NewInt(1))
|
||||||
|
}
|
||||||
|
return !c.IsFeynman(lastBlockNumber, lastBlockTime) && c.IsFeynman(currentBlockNumber, currentBlockTime)
|
||||||
|
}
|
||||||
|
|
||||||
// IsCancun returns whether num is either equal to the Cancun fork time or greater.
|
// IsCancun returns whether num is either equal to the Cancun fork time or greater.
|
||||||
func (c *ChainConfig) IsCancun(num *big.Int, time uint64) bool {
|
func (c *ChainConfig) IsCancun(num *big.Int, time uint64) bool {
|
||||||
return c.IsLondon(num) && isTimestampForked(c.CancunTime, time)
|
return c.IsLondon(num) && isTimestampForked(c.CancunTime, time)
|
||||||
@@ -881,6 +931,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
|
|||||||
{name: "hertzBlock", block: c.HertzBlock},
|
{name: "hertzBlock", block: c.HertzBlock},
|
||||||
{name: "hertzfixBlock", block: c.HertzfixBlock},
|
{name: "hertzfixBlock", block: c.HertzfixBlock},
|
||||||
{name: "keplerTime", timestamp: c.KeplerTime},
|
{name: "keplerTime", timestamp: c.KeplerTime},
|
||||||
|
{name: "feynmanTime", timestamp: c.FeynmanTime},
|
||||||
{name: "cancunTime", timestamp: c.CancunTime, optional: true},
|
{name: "cancunTime", timestamp: c.CancunTime, optional: true},
|
||||||
{name: "pragueTime", timestamp: c.PragueTime, optional: true},
|
{name: "pragueTime", timestamp: c.PragueTime, optional: true},
|
||||||
{name: "verkleTime", timestamp: c.VerkleTime, optional: true},
|
{name: "verkleTime", timestamp: c.VerkleTime, optional: true},
|
||||||
@@ -1020,6 +1071,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int,
|
|||||||
if isForkTimestampIncompatible(c.KeplerTime, newcfg.KeplerTime, headTimestamp) {
|
if isForkTimestampIncompatible(c.KeplerTime, newcfg.KeplerTime, headTimestamp) {
|
||||||
return newTimestampCompatError("Kepler fork timestamp", c.KeplerTime, newcfg.KeplerTime)
|
return newTimestampCompatError("Kepler fork timestamp", c.KeplerTime, newcfg.KeplerTime)
|
||||||
}
|
}
|
||||||
|
if isForkTimestampIncompatible(c.FeynmanTime, newcfg.FeynmanTime, headTimestamp) {
|
||||||
|
return newTimestampCompatError("Feynman fork timestamp", c.FeynmanTime, newcfg.FeynmanTime)
|
||||||
|
}
|
||||||
if isForkTimestampIncompatible(c.CancunTime, newcfg.CancunTime, headTimestamp) {
|
if isForkTimestampIncompatible(c.CancunTime, newcfg.CancunTime, headTimestamp) {
|
||||||
return newTimestampCompatError("Cancun fork timestamp", c.CancunTime, newcfg.CancunTime)
|
return newTimestampCompatError("Cancun fork timestamp", c.CancunTime, newcfg.CancunTime)
|
||||||
}
|
}
|
||||||
@@ -1181,7 +1235,7 @@ type Rules struct {
|
|||||||
IsPlato bool
|
IsPlato bool
|
||||||
IsHertz bool
|
IsHertz bool
|
||||||
IsHertzfix bool
|
IsHertzfix bool
|
||||||
IsShanghai, IsKepler, IsCancun, IsPrague bool
|
IsShanghai, IsKepler, IsFeynman, IsCancun, IsPrague bool
|
||||||
IsVerkle bool
|
IsVerkle bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1213,6 +1267,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
|
|||||||
IsHertzfix: c.IsHertzfix(num),
|
IsHertzfix: c.IsHertzfix(num),
|
||||||
IsShanghai: c.IsShanghai(num, timestamp),
|
IsShanghai: c.IsShanghai(num, timestamp),
|
||||||
IsKepler: c.IsKepler(num, timestamp),
|
IsKepler: c.IsKepler(num, timestamp),
|
||||||
|
IsFeynman: c.IsFeynman(num, timestamp),
|
||||||
IsCancun: c.IsCancun(num, timestamp),
|
IsCancun: c.IsCancun(num, timestamp),
|
||||||
IsPrague: c.IsPrague(num, timestamp),
|
IsPrague: c.IsPrague(num, timestamp),
|
||||||
IsVerkle: c.IsVerkle(num, timestamp),
|
IsVerkle: c.IsVerkle(num, timestamp),
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ const (
|
|||||||
IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation
|
IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation
|
||||||
BlsSignatureVerifyBaseGas uint64 = 1000 // base price for a BLS signature verify operation
|
BlsSignatureVerifyBaseGas uint64 = 1000 // base price for a BLS signature verify operation
|
||||||
BlsSignatureVerifyPerKeyGas uint64 = 3500 // Per-key price for a BLS signature verify operation
|
BlsSignatureVerifyPerKeyGas uint64 = 3500 // Per-key price for a BLS signature verify operation
|
||||||
|
DoubleSignEvidenceVerifyGas uint64 = 1000 // Gas for verify double sign evidence
|
||||||
|
|
||||||
Bn256AddGasByzantium uint64 = 500 // Byzantium gas needed for an elliptic curve addition
|
Bn256AddGasByzantium uint64 = 500 // Byzantium gas needed for an elliptic curve addition
|
||||||
Bn256AddGasIstanbul uint64 = 150 // Gas needed for an elliptic curve addition
|
Bn256AddGasIstanbul uint64 = 150 // Gas needed for an elliptic curve addition
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ func parliaHeaderHashAndRlp(header *types.Header, chainId *big.Int) (hash, rlp [
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
rlp = parlia.ParliaRLP(header, chainId)
|
rlp = parlia.ParliaRLP(header, chainId)
|
||||||
hash = parlia.SealHash(header, chainId).Bytes()
|
hash = types.SealHash(header, chainId).Bytes()
|
||||||
return hash, rlp, err
|
return hash, rlp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user