Skip to content

Commit

Permalink
Implement the eth_sendRawTransaction JSON-RPC endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
m-Peter committed Jan 31, 2024
1 parent cb7c919 commit fb99ac8
Showing 1 changed file with 92 additions and 2 deletions.
94 changes: 92 additions & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ import (
"encoding/hex"
"fmt"
"math/big"
"strings"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"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/eth/filters"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/onflow/cadence"
"github.com/onflow/flow-evm-gateway/storage"
"github.com/onflow/flow-go-sdk"
"github.com/onflow/flow-go-sdk/access"
"github.com/onflow/flow-go-sdk/access/grpc"

sdkCrypto "github.com/onflow/flow-go-sdk/crypto"
)

const EthNamespace = "eth"
Expand Down Expand Up @@ -101,7 +105,93 @@ func (api *BlockChainAPI) SendRawTransaction(
ctx context.Context,
input hexutil.Bytes,
) (common.Hash, error) {
return crypto.Keccak256Hash([]byte("hello world")), nil
gethTx := &types.Transaction{}
encodedLen := uint(len(input))
err := gethTx.DecodeRLP(
rlp.NewStream(
bytes.NewReader(input),
uint64(encodedLen),
),
)
if err != nil {
return common.Hash{}, err
}

flowClient, err := grpc.NewClient(grpc.EmulatorHost)
if err != nil {
return common.Hash{}, err
}

script := `
import EVM from 0xf8d6e0586b0a20c7
transaction(encodedTx: [UInt8]) {
let bridgedAccount: &EVM.BridgedAccount
prepare(signer: auth(Storage) &Account) {
self.bridgedAccount = signer.storage.borrow<&EVM.BridgedAccount>(
from: /storage/evm
) ?? panic("Could not borrow reference to the bridged account!")
}
execute {
EVM.run(tx: encodedTx, coinbase: self.bridgedAccount.address())
log("transaction executed")
}
}
`

block, err := flowClient.GetLatestBlock(context.Background(), true)
if err != nil {
return common.Hash{}, err
}

privateKey, err := sdkCrypto.DecodePrivateKeyHex(sdkCrypto.ECDSA_P256, strings.Replace("2619878f0e2ff438d17835c2a4561cb87b4d24d72d12ec34569acd0dd4af7c21", "0x", "", 1))
if err != nil {
return common.Hash{}, err
}

account, err := flowClient.GetAccount(context.Background(), flow.HexToAddress("0xf8d6e0586b0a20c7"))
if err != nil {
return common.Hash{}, err
}
accountKey := account.Keys[0]
signer, err := sdkCrypto.NewInMemorySigner(privateKey, accountKey.HashAlgo)
if err != nil {
return common.Hash{}, err
}

tx := flow.NewTransaction().
SetScript([]byte(script)).
SetProposalKey(account.Address, accountKey.Index, accountKey.SequenceNumber).
SetReferenceBlockID(block.ID).
SetPayer(account.Address).
AddAuthorizer(account.Address)

decodedTx, err := hex.DecodeString(input.String()[2:])
if err != nil {
return common.Hash{}, err
}
cdcBytes := make([]cadence.Value, 0)
for _, bt := range decodedTx {
cdcBytes = append(cdcBytes, cadence.UInt8(bt))
}
encodedTx := cadence.NewArray(
cdcBytes,
).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type))
tx.AddArgument(encodedTx)

err = tx.SignEnvelope(account.Address, accountKey.Index, signer)
if err != nil {
return common.Hash{}, err
}

err = flowClient.SendTransaction(ctx, *tx)
if err != nil {
return common.Hash{}, err
}

return gethTx.Hash(), nil
}

// eth_createAccessList
Expand Down

0 comments on commit fb99ac8

Please sign in to comment.