Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for backwards mode in avalanche subnets #12039

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions core/scripts/common/avalanche_subnet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package common

import (
"encoding/json"
"errors"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)

// AvaSubnetHeader is a copy of [github.com/ava-labs/subnet-evm/core/types.Header] to avoid importing the whole module.
type AvaSubnetHeader struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner" gencodec:"required"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom AvaBloom `json:"logsBloom" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Number *big.Int `json:"number" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Time uint64 `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce AvaBlockNonce `json:"nonce"`
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
BlockGasCost *big.Int `json:"blockGasCost" rlp:"optional"`
}

func (h *AvaSubnetHeader) UnmarshalJSON(input []byte) error {
type Header struct {
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase *common.Address `json:"miner" gencodec:"required"`
Root *common.Hash `json:"stateRoot" gencodec:"required"`
TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom *AvaBloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash"`
Nonce *AvaBlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
BlockGasCost *hexutil.Big `json:"blockGasCost" rlp:"optional"`
}
var dec Header
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.ParentHash == nil {
return errors.New("missing required field 'parentHash' for Header")
}
h.ParentHash = *dec.ParentHash
if dec.UncleHash == nil {
return errors.New("missing required field 'sha3Uncles' for Header")
}
h.UncleHash = *dec.UncleHash
if dec.Coinbase == nil {
return errors.New("missing required field 'miner' for Header")
}
h.Coinbase = *dec.Coinbase
if dec.Root == nil {
return errors.New("missing required field 'stateRoot' for Header")
}
h.Root = *dec.Root
if dec.TxHash == nil {
return errors.New("missing required field 'transactionsRoot' for Header")
}
h.TxHash = *dec.TxHash
if dec.ReceiptHash == nil {
return errors.New("missing required field 'receiptsRoot' for Header")
}
h.ReceiptHash = *dec.ReceiptHash
if dec.Bloom == nil {
return errors.New("missing required field 'logsBloom' for Header")
}
h.Bloom = *dec.Bloom
if dec.Difficulty == nil {
return errors.New("missing required field 'difficulty' for Header")
}
h.Difficulty = (*big.Int)(dec.Difficulty)
if dec.Number == nil {
return errors.New("missing required field 'number' for Header")
}
h.Number = (*big.Int)(dec.Number)
if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for Header")
}
h.GasLimit = uint64(*dec.GasLimit)
if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for Header")
}
h.GasUsed = uint64(*dec.GasUsed)
if dec.Time == nil {
return errors.New("missing required field 'timestamp' for Header")
}
h.Time = uint64(*dec.Time)
if dec.Extra == nil {
return errors.New("missing required field 'extraData' for Header")
}
h.Extra = *dec.Extra
if dec.MixDigest != nil {
h.MixDigest = *dec.MixDigest
}
if dec.Nonce != nil {
h.Nonce = *dec.Nonce
}
if dec.BaseFee != nil {
h.BaseFee = (*big.Int)(dec.BaseFee)
}
if dec.BlockGasCost != nil {
h.BlockGasCost = (*big.Int)(dec.BlockGasCost)
}
return nil
}

func (h *AvaSubnetHeader) Hash() common.Hash {
return rlpHash(h)
}
29 changes: 25 additions & 4 deletions core/scripts/common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,20 @@ func GetRlpHeaders(env Environment, blockNumbers []*big.Int, getParentBlocks boo
//fmt.Println("Calculated BH:", bh.String(),
// "fetched BH:", h.Hash(),
// "block number:", new(big.Int).Set(blockNum).Add(blockNum, offset).String())
} else if IsAvaxSubnet(env.ChainID) {
var h AvaSubnetHeader
// Get child block since it's the one that has the parent hash in its header.
nextBlockNum := new(big.Int).Set(blockNum).Add(blockNum, offset)
err2 := env.Jc.CallContext(context.Background(), &h, "eth_getBlockByNumber", hexutil.EncodeBig(nextBlockNum), false)
if err2 != nil {
return nil, hashes, fmt.Errorf("failed to get header: %+v", err2)
}
rlpHeader, err2 = rlp.EncodeToBytes(h)
if err2 != nil {
return nil, hashes, fmt.Errorf("failed to encode rlp: %+v", err2)
}

hashes = append(hashes, h.Hash().String())
} else if IsPolygonEdgeNetwork(env.ChainID) {

// Get child block since it's the one that has the parent hash in its header.
Expand Down Expand Up @@ -570,12 +583,20 @@ func CalculateLatestBlockHeader(env Environment, blockNumberInput int) (err erro
return err
}

// IsAvaxNetwork returns true if the given chain ID corresponds to an avalanche network or subnet.
// IsAvaxNetwork returns true if the given chain ID corresponds to an avalanche network.
func IsAvaxNetwork(chainID int64) bool {
return chainID == 43114 || // C-chain mainnet
chainID == 43113 || // Fuji testnet
chainID == 335 || // DFK testnet
chainID == 53935 // DFK mainnet
chainID == 43113 // Fuji testnet
}

// IsAvaxSubnet returns true if the given chain ID corresponds to an avalanche subnet.
func IsAvaxSubnet(chainID int64) bool {
return chainID == 335 || // DFK testnet
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we never ran backwards mode on DFK or we would have run into this issue hehe

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i think we missed it oops

chainID == 53935 || // DFK mainnet
chainID == 955081 || // Nexon Dev
chainID == 595581 || // Nexon Test
chainID == 807424 || // Nexon QA
chainID == 847799 // Nexon Stage
}

func UpkeepLink(chainID int64, upkeepID *big.Int) string {
Expand Down
Loading