mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 12:46:44 +00:00
q
This commit is contained in:
parent
7eac50fe88
commit
06c623b5c7
2 changed files with 198 additions and 27 deletions
|
|
@ -27,11 +27,23 @@ import (
|
||||||
"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/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/params/forks"
|
"github.com/ethereum/go-ethereum/params/forks"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type backend interface {
|
||||||
|
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
||||||
|
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
|
||||||
|
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
|
||||||
|
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
|
||||||
|
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
|
||||||
|
GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64)
|
||||||
|
GetPoolTransaction(txHash common.Hash) *types.Transaction
|
||||||
|
ChainConfig() *params.ChainConfig
|
||||||
|
}
|
||||||
|
|
||||||
type execApiServer struct {
|
type execApiServer struct {
|
||||||
apiBackend backend
|
apiBackend backend
|
||||||
}
|
}
|
||||||
|
|
@ -40,17 +52,17 @@ func ExecutionAPI(server *Server, backend backend) API {
|
||||||
api := execApiServer{apiBackend: backend}
|
api := execApiServer{apiBackend: backend}
|
||||||
return func(router *mux.Router) {
|
return func(router *mux.Router) {
|
||||||
router.HandleFunc("/eth/v1/exec/headers/{blockid}", server.WrapHandler(api.handleHeaders, false, false, true)).Methods("GET")
|
router.HandleFunc("/eth/v1/exec/headers/{blockid}", server.WrapHandler(api.handleHeaders, false, false, true)).Methods("GET")
|
||||||
router.HandleFunc("/eth/v1/exec/blocks", server.WrapHandler(api.handleBlocks, false, false, true)).Methods("GET")
|
router.HandleFunc("/eth/v1/exec/blocks/{blockid}", server.WrapHandler(api.handleBlocks, false, false, true)).Methods("GET")
|
||||||
router.HandleFunc("/eth/v1/exec/block_receipts", server.WrapHandler(api.handleBlockReceipts, false, false, true)).Methods("GET")
|
router.HandleFunc("/eth/v1/exec/block_receipts/{blockid}", server.WrapHandler(api.handleBlockReceipts, false, false, true)).Methods("GET")
|
||||||
router.HandleFunc("/eth/v1/exec/transaction", server.WrapHandler(api.handleTransaction, false, false, true)).Methods("GET")
|
router.HandleFunc("/eth/v1/exec/transaction/{txhash}", server.WrapHandler(api.handleTransaction, false, false, true)).Methods("GET")
|
||||||
router.HandleFunc("/eth/v1/exec/transaction_by_index", server.WrapHandler(api.handleTxByIndex, false, false, true)).Methods("GET")
|
router.HandleFunc("/eth/v1/exec/transaction_by_index/{blockid}", server.WrapHandler(api.handleTxByIndex, false, false, true)).Methods("GET")
|
||||||
router.HandleFunc("/eth/v1/exec/receipt_by_index", server.WrapHandler(api.handleReceiptByIndex, false, false, true)).Methods("GET")
|
router.HandleFunc("/eth/v1/exec/receipt_by_index/{blockid}", server.WrapHandler(api.handleReceiptByIndex, false, false, true)).Methods("GET")
|
||||||
router.HandleFunc("/eth/v1/exec/state", server.WrapHandler(api.handleState, true, true, true)).Methods("POST")
|
router.HandleFunc("/eth/v1/exec/state/{blockid}", server.WrapHandler(api.handleState, true, true, true)).Methods("POST")
|
||||||
router.HandleFunc("/eth/v1/exec/call", server.WrapHandler(api.handleCall, true, true, true)).Methods("POST")
|
router.HandleFunc("/eth/v1/exec/call/{blockid}", server.WrapHandler(api.handleCall, true, true, true)).Methods("POST")
|
||||||
router.HandleFunc("/eth/v1/exec/send_transaction", server.WrapHandler(api.handleSendTransaction, true, true, true)).Methods("POST")
|
router.HandleFunc("/eth/v1/exec/send_transaction", server.WrapHandler(api.handleSendTransaction, true, true, true)).Methods("POST")
|
||||||
router.HandleFunc("/eth/v1/exec/history", server.WrapHandler(api.handleHistory, false, false, true)).Methods("GET")
|
/*router.HandleFunc("/eth/v1/exec/history", server.WrapHandler(api.handleHistory, false, false, true)).Methods("GET")
|
||||||
router.HandleFunc("/eth/v1/exec/transaction_position", server.WrapHandler(api.handleTxPosition, false, false, true)).Methods("GET")
|
router.HandleFunc("/eth/v1/exec/transaction_position", server.WrapHandler(api.handleTxPosition, false, false, true)).Methods("GET")
|
||||||
router.HandleFunc("/eth/v1/exec/logs", server.WrapHandler(api.handleLogs, false, false, true)).Methods("GET")
|
router.HandleFunc("/eth/v1/exec/logs", server.WrapHandler(api.handleLogs, false, false, true)).Methods("GET")*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,7 +161,7 @@ func (s *execApiServer) handleHeaders(ctx context.Context, values url.Values, va
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
return nil, "request timeout", http.StatusRequestTimeout
|
return nil, "request timeout", http.StatusRequestTimeout
|
||||||
}
|
}
|
||||||
if response[i].Data == nil {
|
if response[i].Data == nil || err != nil {
|
||||||
return nil, "not available", http.StatusNotFound
|
return nil, "not available", http.StatusNotFound
|
||||||
}
|
}
|
||||||
response[i].Version = s.forkName(response[i].Data)
|
response[i].Version = s.forkName(response[i].Data)
|
||||||
|
|
@ -163,26 +175,195 @@ func (s *execApiServer) handleHeaders(ctx context.Context, values url.Values, va
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *execApiServer) handleBlocks(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
func (s *execApiServer) handleBlocks(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
||||||
panic("TODO")
|
type blockResponse struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
Data *types.Block `json:"data"`
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
amount int
|
||||||
|
response []blockResponse
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
id, ok := getBlockId(vars["blockid"])
|
||||||
|
if !ok {
|
||||||
|
return nil, "invalid block id", http.StatusBadRequest
|
||||||
|
}
|
||||||
|
if s := values.Get("amount"); s != "" {
|
||||||
|
amount, err = strconv.Atoi(s)
|
||||||
|
if err != nil || amount <= 0 {
|
||||||
|
return nil, "invalid amount", http.StatusBadRequest
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
amount = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
response = make([]blockResponse, amount)
|
||||||
|
for i := amount - 1; i >= 0; i-- {
|
||||||
|
if id.isHash() {
|
||||||
|
response[i].Data, err = s.apiBackend.BlockByHash(ctx, id.hash)
|
||||||
|
} else {
|
||||||
|
response[i].Data, err = s.apiBackend.BlockByNumber(ctx, rpc.BlockNumber(id.number))
|
||||||
|
}
|
||||||
|
if errors.Is(err, context.Canceled) {
|
||||||
|
return nil, "request timeout", http.StatusRequestTimeout
|
||||||
|
}
|
||||||
|
if response[i].Data == nil || err != nil {
|
||||||
|
return nil, "not available", http.StatusNotFound
|
||||||
|
}
|
||||||
|
response[i].Version = s.forkName(response[i].Data.Header())
|
||||||
|
if response[i].Data.NumberU64() == 0 {
|
||||||
|
response = response[i:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
id = blockId{hash: response[i].Data.ParentHash()}
|
||||||
|
}
|
||||||
|
return response, "", 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *execApiServer) handleBlockReceipts(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
func (s *execApiServer) handleBlockReceipts(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
||||||
panic("TODO")
|
type blockReceiptsResponse struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
Data types.Receipts `json:"data"`
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
amount int
|
||||||
|
response []blockReceiptsResponse
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
id, ok := getBlockId(vars["blockid"])
|
||||||
|
if !ok {
|
||||||
|
return nil, "invalid block id", http.StatusBadRequest
|
||||||
|
}
|
||||||
|
if s := values.Get("amount"); s != "" {
|
||||||
|
amount, err = strconv.Atoi(s)
|
||||||
|
if err != nil || amount <= 0 {
|
||||||
|
return nil, "invalid amount", http.StatusBadRequest
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
amount = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
response = make([]blockReceiptsResponse, amount)
|
||||||
|
for i := amount - 1; i >= 0; i-- {
|
||||||
|
var header *types.Header
|
||||||
|
if id.isHash() {
|
||||||
|
header, err = s.apiBackend.HeaderByHash(ctx, id.hash)
|
||||||
|
} else {
|
||||||
|
header, err = s.apiBackend.HeaderByNumber(ctx, rpc.BlockNumber(id.number))
|
||||||
|
}
|
||||||
|
if header != nil && err == nil {
|
||||||
|
response[i].Data, err = s.apiBackend.GetReceipts(ctx, header.Hash())
|
||||||
|
}
|
||||||
|
if errors.Is(err, context.Canceled) {
|
||||||
|
return nil, "request timeout", http.StatusRequestTimeout
|
||||||
|
}
|
||||||
|
if response[i].Data == nil || err != nil {
|
||||||
|
return nil, "not available", http.StatusNotFound
|
||||||
|
}
|
||||||
|
response[i].Version = s.forkName(header)
|
||||||
|
if header.Number.Uint64() == 0 {
|
||||||
|
response = response[i:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
id = blockId{hash: header.ParentHash}
|
||||||
|
}
|
||||||
|
return response, "", 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *execApiServer) handleTransaction(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
func (s *execApiServer) handleTransaction(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
||||||
panic("TODO")
|
var txHash common.Hash
|
||||||
|
if hex, err := hexutil.Decode(vars["txhash"]); err == nil {
|
||||||
|
if len(hex) != common.HashLength {
|
||||||
|
return nil, "invalid transaction hash", http.StatusBadRequest
|
||||||
|
}
|
||||||
|
copy(txHash[:], hex)
|
||||||
|
}
|
||||||
|
_, tx, _, _, _ := s.apiBackend.GetCanonicalTransaction(txHash)
|
||||||
|
if tx == nil {
|
||||||
|
tx = s.apiBackend.GetPoolTransaction(txHash)
|
||||||
|
}
|
||||||
|
if tx == nil {
|
||||||
|
return nil, "not available", http.StatusNotFound
|
||||||
|
}
|
||||||
|
return tx, "", 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *execApiServer) handleTxByIndex(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
func (s *execApiServer) handleTxByIndex(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
||||||
panic("TODO")
|
type txProof struct {
|
||||||
|
Index uint64 `json:"index"`
|
||||||
|
Transaction *types.Transaction `json:"transaction" rlp:"-"`
|
||||||
|
Proof []hexutil.Bytes `json:"proof"`
|
||||||
|
}
|
||||||
|
var response struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
Data types.Receipts `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
id, ok := getBlockId(vars["blockid"])
|
||||||
|
if !ok {
|
||||||
|
return nil, "invalid block id", http.StatusBadRequest
|
||||||
|
}
|
||||||
|
indices := values["indices"]
|
||||||
|
if len(indices) == 0 {
|
||||||
|
return nil, "empty transaction index list", http.StatusBadRequest
|
||||||
|
}
|
||||||
|
response.Data = make([]txProof, len(indices))
|
||||||
|
for i, str := range indicesStr {
|
||||||
|
if number, err := strconv.ParseUint(str, 10, 64); err == nil {
|
||||||
|
indices[i] = number
|
||||||
|
} else {
|
||||||
|
return nil, "invalid transaction index", http.StatusBadRequest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
block *types.Block
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if id.isHash() {
|
||||||
|
block, err = s.apiBackend.BlockByHash(ctx, id.hash)
|
||||||
|
} else {
|
||||||
|
block, err = s.apiBackend.BlockByNumber(ctx, rpc.BlockNumber(id.number))
|
||||||
|
}
|
||||||
|
if errors.Is(err, context.Canceled) {
|
||||||
|
return nil, "request timeout", http.StatusRequestTimeout
|
||||||
|
}
|
||||||
|
if block == nil || err != nil {
|
||||||
|
return nil, "not available", http.StatusNotFound
|
||||||
|
}
|
||||||
|
response[i].Version = s.forkName(block.Header())
|
||||||
|
t := trie.NewStackTrie(nil)
|
||||||
|
if types.DeriveSha(block.Transactions(), t) != block.TransactionsRoot() {
|
||||||
|
log.Error("")
|
||||||
|
return nil, "transactions root mismatch", http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
var indexBuf []byte
|
||||||
|
for _, txIndex := range indices {
|
||||||
|
indexBuf = rlp.AppendUint64(indexBuf[:0], txIndex)
|
||||||
|
t.Prove(indexBuf, proofWriter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *execApiServer) handleReceiptByIndex(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
func (s *execApiServer) handleReceiptByIndex(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
||||||
panic("TODO")
|
id, ok := getBlockId(vars["blockid"])
|
||||||
|
if !ok {
|
||||||
|
return nil, "invalid block id", http.StatusBadRequest
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *execApiServer) handleState(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
func (s *execApiServer) handleState(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
||||||
panic("TODO")
|
id, ok := getBlockId(vars["blockid"])
|
||||||
|
if !ok {
|
||||||
|
return nil, "invalid block id", http.StatusBadRequest
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *execApiServer) handleCall(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
func (s *execApiServer) handleCall(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
||||||
panic("TODO")
|
id, ok := getBlockId(vars["blockid"])
|
||||||
|
if !ok {
|
||||||
|
return nil, "invalid block id", http.StatusBadRequest
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *execApiServer) handleHistory(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
func (s *execApiServer) handleHistory(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int) {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
} // Requires EIP-7745
|
} // Requires EIP-7745
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/elnormous/contenttype"
|
"github.com/elnormous/contenttype"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -41,12 +37,6 @@ type Server struct {
|
||||||
|
|
||||||
type API func(*mux.Router)
|
type API func(*mux.Router)
|
||||||
|
|
||||||
type backend interface {
|
|
||||||
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
|
||||||
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
|
|
||||||
ChainConfig() *params.ChainConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
type WrappedHandler func(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int)
|
type WrappedHandler func(ctx context.Context, values url.Values, vars map[string]string, decodeBody func(*any) error) (any, string, int)
|
||||||
|
|
||||||
func NewServer(node *node.Node) *Server {
|
func NewServer(node *node.Node) *Server {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue