Skip to content

Commit

Permalink
Merge pull request #1124 from maticnetwork/consistent
Browse files Browse the repository at this point in the history
Consistent
  • Loading branch information
temaniarpit27 authored Jan 19, 2024
2 parents 70bebc9 + b54c9b9 commit 603a425
Show file tree
Hide file tree
Showing 18 changed files with 704 additions and 50 deletions.
4 changes: 4 additions & 0 deletions consensus/bor/bor.go
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,10 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.State
for addr, account := range allocs {
log.Info("change contract code", "address", addr)
state.SetCode(addr, account.Code)

if state.GetBalance(addr).Cmp(big.NewInt(0)) == 0 {
state.SetBalance(addr, account.Balance)
}
}
}
}
Expand Down
31 changes: 24 additions & 7 deletions consensus/bor/bor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ func TestGenesisContractChange(t *testing.T) {
"balance": "0x1000",
},
},
"6": map[string]interface{}{
addr0.Hex(): map[string]interface{}{
"code": hexutil.Bytes{0x1, 0x4},
"balance": "0x2000",
},
},
},
},
}
Expand Down Expand Up @@ -85,24 +91,35 @@ func TestGenesisContractChange(t *testing.T) {

root := genesis.Root()

// code does not change
// code does not change, balance remains 0
root, statedb = addBlock(root, 1)
require.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x1})
require.Equal(t, statedb.GetBalance(addr0), big.NewInt(0))

// code changes 1st time
// code changes 1st time, balance remains 0
root, statedb = addBlock(root, 2)
require.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x2})
require.Equal(t, statedb.GetBalance(addr0), big.NewInt(0))

// code same as 1st change
// code same as 1st change, balance remains 0
root, statedb = addBlock(root, 3)
require.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x2})
require.Equal(t, statedb.GetBalance(addr0), big.NewInt(0))

// code changes 2nd time
_, statedb = addBlock(root, 4)
// code changes 2nd time, balance updates to 4096
root, statedb = addBlock(root, 4)
require.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x3})
require.Equal(t, statedb.GetBalance(addr0), big.NewInt(4096))

// make sure balance change DOES NOT take effect
require.Equal(t, statedb.GetBalance(addr0), big.NewInt(0))
// code same as 2nd change, balance remains 4096
root, statedb = addBlock(root, 5)
require.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x3})
require.Equal(t, statedb.GetBalance(addr0), big.NewInt(4096))

// code changes 3rd time, balance remains 4096
_, statedb = addBlock(root, 6)
require.Equal(t, statedb.GetCode(addr0), []byte{0x1, 0x4})
require.Equal(t, statedb.GetBalance(addr0), big.NewInt(4096))
}

func TestEncodeSigHeaderJaipur(t *testing.T) {
Expand Down
16 changes: 14 additions & 2 deletions core/txpool/legacypool/legacypool.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ var DefaultConfig = Config{
AccountQueue: 64,
GlobalQueue: 1024,

Lifetime: 3 * time.Hour,
Lifetime: 3 * time.Hour,
AllowUnprotectedTxs: false,
}

// sanitize checks the provided user configurations and changes anything that's
Expand Down Expand Up @@ -590,7 +591,8 @@ func (pool *LegacyPool) local() map[common.Address]types.Transactions {
// and does not require the pool mutex to be held.
func (pool *LegacyPool) validateTxBasics(tx *types.Transaction, local bool) error {
opts := &txpool.ValidationOptions{
Config: pool.chainconfig,
Config: pool.chainconfig,
AllowUnprotectedTxs: pool.config.AllowUnprotectedTxs,
Accept: 0 |
1<<types.LegacyTxType |
1<<types.AccessListTxType |
Expand Down Expand Up @@ -660,6 +662,11 @@ func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, e
knownTxMeter.Mark(1)
return false, ErrAlreadyKnown
}

if pool.config.AllowUnprotectedTxs {
pool.signer = types.NewFakeSigner(tx.ChainId())
}

// Make the local flag. If it's from local source or it's from the network but
// the sender is marked as local previously, treat it as the local transaction.
isLocal := local || pool.locals.containsTx(tx)
Expand Down Expand Up @@ -982,6 +989,11 @@ func (pool *LegacyPool) addTxs(txs []*types.Transaction, local, sync bool) []err
knownTxMeter.Mark(1)
continue
}

if pool.config.AllowUnprotectedTxs {
pool.signer = types.NewFakeSigner(tx.ChainId())
}

// Exclude transactions with basic errors, e.g invalid signatures and
// insufficient intrinsic gas as soon as possible and cache senders
// in transactions before obtaining lock
Expand Down
4 changes: 3 additions & 1 deletion core/txpool/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import (
type ValidationOptions struct {
Config *params.ChainConfig // Chain configuration to selectively validate based on current fork rules

AllowUnprotectedTxs bool // Whether to allow unprotected transactions in the pool

Accept uint8 // Bitmap of transaction types that should be accepted for the calling pool
MaxSize uint64 // Maximum size of a transaction that the caller can meaningfully handle
MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool
Expand Down Expand Up @@ -91,7 +93,7 @@ func ValidateTransaction(tx *types.Transaction, blobs []kzg4844.Blob, commits []
return core.ErrTipAboveFeeCap
}
// Make sure the transaction is signed properly
if _, err := types.Sender(signer, tx); err != nil {
if _, err := types.Sender(signer, tx); err != nil && !opts.AllowUnprotectedTxs {
return ErrInvalidSender
}
// Ensure the transaction has more gas than the bare minimum needed to cover
Expand Down
35 changes: 35 additions & 0 deletions core/types/transaction_signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,3 +594,38 @@ func deriveChainId(v *big.Int) *big.Int {
v = new(big.Int).Sub(v, big.NewInt(35))
return v.Div(v, big.NewInt(2))
}

// FakeSigner implements the Signer interface and accepts unprotected transactions
type FakeSigner struct{ londonSigner }

var _ Signer = FakeSigner{}

func NewFakeSigner(chainId *big.Int) Signer {
signer := NewLondonSigner(chainId)
ls, _ := signer.(londonSigner)
return FakeSigner{londonSigner: ls}
}

func (f FakeSigner) Sender(tx *Transaction) (common.Address, error) {
return f.londonSigner.Sender(tx)
}

func (f FakeSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) {
return f.londonSigner.SignatureValues(tx, sig)
}

func (f FakeSigner) ChainID() *big.Int {
return f.londonSigner.ChainID()
}

// Hash returns 'signature hash', i.e. the transaction hash that is signed by the
// private key. This hash does not uniquely identify the transaction.
func (f FakeSigner) Hash(tx *Transaction) common.Hash {
return f.londonSigner.Hash(tx)
}

// Equal returns true if the given signer is the same as the receiver.
func (f FakeSigner) Equal(Signer) bool {
// Always return true
return true
}
56 changes: 46 additions & 10 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/crypto/bls12381"
"github.com/ethereum/go-ethereum/crypto/bn256"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/crypto/secp256r1"
"github.com/ethereum/go-ethereum/params"
"golang.org/x/crypto/ripemd160"
)
Expand Down Expand Up @@ -95,16 +96,17 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
// PrecompiledContractsCancun contains the default set of pre-compiled Ethereum
// contracts used in the Cancun release.
var PrecompiledContractsCancun = 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{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{9}): &blake2F{},
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
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{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{9}): &blake2F{},
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
}

// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
Expand Down Expand Up @@ -1194,3 +1196,37 @@ func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash {

return h
}

// P256VERIFY (secp256r1 signature verification)
// implemented as a native contract
type p256Verify struct{}

// RequiredGas returns the gas required to execute the precompiled contract
func (c *p256Verify) RequiredGas(input []byte) uint64 {
return params.P256VerifyGas
}

// Run executes the precompiled contract with given 160 bytes of param, returning the output and the used gas
func (c *p256Verify) Run(input []byte) ([]byte, error) {
// Required input length is 160 bytes
const p256VerifyInputLength = 160
// Check the input length
if len(input) != p256VerifyInputLength {
// Input length is invalid
return nil, nil
}

// Extract the hash, r, s, x, y from the input
hash := input[0:32]
r, s := new(big.Int).SetBytes(input[32:64]), new(big.Int).SetBytes(input[64:96])
x, y := new(big.Int).SetBytes(input[96:128]), new(big.Int).SetBytes(input[128:160])

// Verify the secp256r1 signature
if secp256r1.Verify(hash, r, s, x, y) {
// Signature is valid
return common.LeftPadBytes(common.Big1.Bytes(), 32), nil
} else {
// Signature is invalid
return nil, nil
}
}
17 changes: 17 additions & 0 deletions core/vm/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x0f, 0x10}): &bls12381Pairing{},
common.BytesToAddress([]byte{0x0f, 0x11}): &bls12381MapG1{},
common.BytesToAddress([]byte{0x0f, 0x12}): &bls12381MapG2{},
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
}

// EIP-152 test vectors
Expand Down Expand Up @@ -415,3 +416,19 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
}
benchmarkPrecompiled("0f", testcase, b)
}

// Benchmarks the sample inputs from the P256VERIFY precompile.
func BenchmarkPrecompiledP256Verify(bench *testing.B) {
t := precompiledTest{
Input: "4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e",
Expected: "0000000000000000000000000000000000000000000000000000000000000001",
Name: "p256Verify",
}
benchmarkPrecompiled("100", t, bench)
}

func TestPrecompiledP256Verify(t *testing.T) {
t.Parallel()

testJson("p256Verify", "100", t)
}
37 changes: 37 additions & 0 deletions core/vm/testdata/precompiles/p256Verify.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"Input": "4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e",
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
"Gas": 3450,
"Name": "CallP256Verify",
"NoBenchmark": false
},
{
"Input": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9414de3726ee4d237b410c1d85ebcb05553dc578561d9f7942b7250795beb9b9027b657067322fc00ab35263fde0acabf998cd9fcf1282df9555f85dba7bdbbe2dc90f74c9e210bc3e0c60aeaa03729c9e6acde4a048ee58fd2e466c1e7b0374e606b8c22ad2985df7d792ff344f03ce94a079da801006b13640bc5af7932a7b9",
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
"Gas": 3450,
"Name": "CallP256Verify",
"NoBenchmark": false
},
{
"Input": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9b35d6a4f7f6fc5620c97d4287696f5174b3d37fa537b74b5fc26997ba79c725d62fe5e5fe6da76eec924e822c5ef853ede6c17069a9e9133a38f87d61599f68e7d5f3c812a255436846ee84a262b79ec4d0783afccf2433deabdca9ecf62bef5ff24e90988c7f139d378549c3a8bc6c94e6a1c911c1e02e6f48ed65aaf3d296e",
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
"Gas": 3450,
"Name": "CallP256Verify",
"NoBenchmark": false
},
{
"Input": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9c29c3df6ce3431b6f030b1b68b1589508ad9d1a149830489c638653aa4b08af93f6e86a9a7643403b6f5c593410d9f7234a8cd27309bce90447073ce17476850615ff147863bc8652be1e369444f90bbc5f9df05a26362e609f73ab1f1839fe3cd34fd2ae672c110671d49115825fc56b5148321aabe5ba39f2b46f71149cff9",
"Expected": "",
"Gas": 3450,
"Name": "CallP256Verify",
"NoBenchmark": false
},
{
"Input": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
"Expected": "",
"Gas": 3450,
"Name": "CallP256Verify",
"NoBenchmark": false
}
]
26 changes: 26 additions & 0 deletions crypto/secp256r1/publickey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package secp256r1

import (
"crypto/ecdsa"
"crypto/elliptic"
"math/big"
)

// Generates approptiate public key format from given coordinates
func newPublicKey(x, y *big.Int) *ecdsa.PublicKey {
// Check if the given coordinates are valid
if x == nil || y == nil || !elliptic.P256().IsOnCurve(x, y) {
return nil
}

// Check if the given coordinates are the reference point (infinity)
if x.Sign() == 0 && y.Sign() == 0 {
return nil
}

return &ecdsa.PublicKey{
Curve: elliptic.P256(),
X: x,
Y: y,
}
}
21 changes: 21 additions & 0 deletions crypto/secp256r1/verifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package secp256r1

import (
"crypto/ecdsa"
"math/big"
)

// Verifies the given signature (r, s) for the given hash and public key (x, y).
func Verify(hash []byte, r, s, x, y *big.Int) bool {
// Create the public key format
publicKey := newPublicKey(x, y)

// Check if they are invalid public key coordinates
if publicKey == nil {
return false
}

// Verify the signature with the public key,
// then return true if it's valid, false otherwise
return ecdsa.Verify(publicKey, hash, r, s)
}
3 changes: 1 addition & 2 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {

eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil}
if eth.APIBackend.allowUnprotectedTxs {
log.Debug(" ###########", "Unprotected transactions allowed")

log.Info("------Unprotected transactions allowed-------")
config.TxPool.AllowUnprotectedTxs = true
}

Expand Down
15 changes: 0 additions & 15 deletions eth/bor_api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,6 @@ func (b *EthAPIBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, e
return false, fmt.Errorf("Hash mismatch: localChainHash %s, milestoneHash %s", localEndBlockHash, hash)
}

ethHandler := (*ethHandler)(b.eth.handler)

bor, ok := ethHandler.chain.Engine().(*bor.Bor)

if !ok {
return false, fmt.Errorf("Bor not available")
}

err = bor.HeimdallClient.FetchMilestoneID(ctx, milestoneId)

if err != nil {
downloader.UnlockMutex(false, "", endBlockNr, common.Hash{})
return false, fmt.Errorf("Milestone ID doesn't exist in Heimdall")
}

downloader.UnlockMutex(true, milestoneId, endBlockNr, localEndBlock.Hash())

return true, nil
Expand Down
Loading

0 comments on commit 603a425

Please sign in to comment.