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

Optimize format for EVM txs & data #124

Merged
merged 3 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
14 changes: 12 additions & 2 deletions integration/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import (
_ "embed"
"encoding/hex"
"fmt"
"github.com/onflow/flow-go-sdk/access/grpc"
"github.com/onflow/flow-go/fvm/evm/types"
"math/big"
"testing"
"time"

"github.com/onflow/flow-go-sdk/access/grpc"
"github.com/onflow/flow-go/fvm/evm/types"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/params"
"github.com/onflow/flow-evm-gateway/bootstrap"
Expand Down Expand Up @@ -580,6 +581,15 @@ func TestE2E_API_DeployEvents(t *testing.T) {

time.Sleep(1 * time.Second)

// perform `eth_call` to read the stored value
storedValue, err := rpcTester.call(contractAddress, callRetrieve)
require.NoError(t, err)
assert.Equal(
t,
"0000000000000000000000000000000000000000000000000000000000000539",
turbolent marked this conversation as resolved.
Show resolved Hide resolved
hex.EncodeToString(storedValue),
)

// check if the sender account nonce has been indexed as increased
eoaNonce, err = rpcTester.getNonce(fundEOAAddress)
require.NoError(t, err)
Expand Down
25 changes: 25 additions & 0 deletions integration/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,31 @@ func (r *rpcTest) estimateGas(
return gasUsed, nil
}

func (r *rpcTest) call(
to common.Address,
data []byte,
) ([]byte, error) {
rpcRes, err := r.request(
"eth_call",
fmt.Sprintf(
`[{"to":"%s","data":"0x%s"}]`,
to.Hex(),
hex.EncodeToString(data),
),
)
if err != nil {
return nil, err
}

var result hexutil.Bytes
err = json.Unmarshal(rpcRes, &result)
if err != nil {
return nil, err
}

return result, nil
}

func uintHex(x uint64) string {
return fmt.Sprintf("0x%x", x)
}
Expand Down
9 changes: 5 additions & 4 deletions services/requester/cadence/call.cdc
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import EVM

access(all)
fun main(data: [UInt8], contractAddress: [UInt8; 20]): [UInt8] {
fun main(hexEncodedData: String, contractAddress: [UInt8; 20]): [UInt8] {
turbolent marked this conversation as resolved.
Show resolved Hide resolved
let account = getAuthAccount<auth(Storage) &Account>(Address(0xCOA))

let coa = account.storage.borrow<auth(EVM.Call) &EVM.CadenceOwnedAccount>(from: /storage/evm)
?? panic("Could not borrow reference to the COA!")
let coa = account.storage.borrow<auth(EVM.Call) &EVM.CadenceOwnedAccount>(
from: /storage/evm
) ?? panic("Could not borrow reference to the COA!")

return coa.call(
to: EVM.EVMAddress(bytes: contractAddress),
data: data,
data: hexEncodedData.decodeHex(),
gasLimit: 15000000, // todo make it configurable, max for now
value: EVM.Balance(attoflow: 0)
).data
Expand Down
4 changes: 2 additions & 2 deletions services/requester/cadence/estimate_gas.cdc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import EVM

access(all)
fun main(encodedTx: [UInt8]): [UInt64; 2] {
fun main(hexEncodedTx: String): [UInt64; 2] {
let account = getAuthAccount<auth(Storage) &Account>(Address(0xCOA))

let coa = account.storage.borrow<&EVM.CadenceOwnedAccount>(
from: /storage/evm
) ?? panic("Could not borrow reference to the COA!")
let txResult = EVM.run(tx: encodedTx, coinbase: coa.address())
let txResult = EVM.run(tx: hexEncodedTx.decodeHex(), coinbase: coa.address())

return [txResult.errorCode, txResult.gasUsed]
}
13 changes: 7 additions & 6 deletions services/requester/cadence/run.cdc
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import EVM

transaction(encodedTx: [UInt8]) {
transaction(hexEncodedTx: String) {
let coa: &EVM.CadenceOwnedAccount

prepare(signer: auth(Storage) &Account) {
self.coa = signer.storage.borrow<&EVM.CadenceOwnedAccount>(from: /storage/evm)
?? panic("Could not borrow reference to the bridged account!")
self.coa = signer.storage.borrow<&EVM.CadenceOwnedAccount>(
from: /storage/evm
) ?? panic("Could not borrow reference to the COA!")
}

execute {
let result = EVM.run(tx: encodedTx, coinbase: self.coa.address())
let txResult = EVM.run(tx: hexEncodedTx.decodeHex(), coinbase: self.coa.address())
// todo only temporary until we correctly handle failure events
assert(
result.status == EVM.Status.successful,
message: "failed to execute evm transaction: ".concat(result.errorCode.toString())
txResult.status == EVM.Status.successful,
message: "failed to execute evm transaction: ".concat(txResult.errorCode.toString())
)
}
}
34 changes: 21 additions & 13 deletions services/requester/requester.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import (
"bytes"
"context"
_ "embed"
"encoding/hex"
"fmt"
"math/big"
"strings"

"github.com/ethereum/go-ethereum/common"
gethCore "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
Expand All @@ -19,8 +23,6 @@ import (
flowGo "github.com/onflow/flow-go/model/flow"
"github.com/rs/zerolog"
"golang.org/x/sync/errgroup"
"math/big"
"strings"
)

var (
Expand All @@ -42,8 +44,7 @@ var (
//go:embed cadence/get_nonce.cdc
getNonceScript []byte

byteArrayType = cadence.NewVariableSizedArrayType(cadence.UInt8Type)
addressType = cadence.NewConstantSizedArrayType(
addressType = cadence.NewConstantSizedArrayType(
common.AddressLength,
cadence.UInt8Type,
)
Expand Down Expand Up @@ -154,13 +155,14 @@ func (e *EVM) SendRawTransaction(ctx context.Context, data []byte) (common.Hash,
return common.Hash{}, err
}

hexEncodedTx, err := cadence.NewString(hex.EncodeToString(data))
if err != nil {
return common.Hash{}, err
}

// todo make sure the gas price is not bellow the configured gas price
script := e.replaceAddresses(runTxScript)
flowID, err := e.signAndSend(
ctx,
script,
cadenceArrayFromBytes(data),
)
flowID, err := e.signAndSend(ctx, script, hexEncodedTx)
if err != nil {
return common.Hash{}, err
}
Expand Down Expand Up @@ -289,8 +291,11 @@ func (e *EVM) GetNonce(ctx context.Context, address common.Address) (uint64, err
}

func (e *EVM) Call(ctx context.Context, address common.Address, data []byte) ([]byte, error) {
hexEncodedData, err := cadence.NewString(hex.EncodeToString(data))
if err != nil {
return nil, err
}
// todo make "to" address optional, this can be used for contract deployment simulations
txData := cadenceArrayFromBytes(data).WithType(byteArrayType)
toAddress := cadenceArrayFromBytes(address.Bytes()).WithType(addressType)

e.logger.Debug().
Expand All @@ -301,7 +306,7 @@ func (e *EVM) Call(ctx context.Context, address common.Address, data []byte) ([]
value, err := e.client.ExecuteScriptAtLatestBlock(
ctx,
e.replaceAddresses(callScript),
[]cadence.Value{txData, toAddress},
[]cadence.Value{hexEncodedData, toAddress},
)
if err != nil {
return nil, fmt.Errorf("failed to execute script: %w", err)
Expand All @@ -321,12 +326,15 @@ func (e *EVM) EstimateGas(ctx context.Context, data []byte) (uint64, error) {
Str("data", fmt.Sprintf("%x", data)).
Msg("estimate gas")

txData := cadenceArrayFromBytes(data).WithType(byteArrayType)
hexEncodedTx, err := cadence.NewString(hex.EncodeToString(data))
if err != nil {
return 0, err
}

value, err := e.client.ExecuteScriptAtLatestBlock(
ctx,
e.replaceAddresses(estimateGasScript),
[]cadence.Value{txData},
[]cadence.Value{hexEncodedTx},
)
if err != nil {
return 0, fmt.Errorf("failed to execute script: %w", err)
Expand Down
Loading