From b9cba16b813f184e4655ce12e9e1174b66ecc241 Mon Sep 17 00:00:00 2001 From: halo3mic <46010359+halo3mic@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:12:06 -0400 Subject: [PATCH] add http-requests precompile --- core/types/suave_structs.go | 2 +- core/vm/contracts_suave.go | 46 +++++++++++++++++ core/vm/contracts_suave_runtime_adapter.go | 50 ++++++++++++++++++- .../contracts_suave_runtime_adapter_test.go | 6 +++ core/vm/contracts_suave_test.go | 30 +++++++++++ suave/artifacts/SuaveLib.json | 2 +- suave/artifacts/addresses.go | 6 ++- suave/gen/suave_spec.yaml | 12 +++++ suave/sol/libraries/Suave.sol | 14 ++++++ 9 files changed, 163 insertions(+), 5 deletions(-) diff --git a/core/types/suave_structs.go b/core/types/suave_structs.go index 70728aac8..82ac4472e 100755 --- a/core/types/suave_structs.go +++ b/core/types/suave_structs.go @@ -1,5 +1,5 @@ // Code generated by suave/gen. DO NOT EDIT. -// Hash: 58abede869b35f32efbb95ee4b2c2eff30631ae4ecb4f2732cd972174fe95ced +// Hash: 0f81d89c49fab4d406fc8b2116dee34a700fe51f246ba99c831af8be8975300e package types import "github.com/ethereum/go-ethereum/common" diff --git a/core/vm/contracts_suave.go b/core/vm/contracts_suave.go index 3c4992374..de7f64a67 100644 --- a/core/vm/contracts_suave.go +++ b/core/vm/contracts_suave.go @@ -9,6 +9,7 @@ import ( "net/http" "net/url" "strings" + "sync" "time" "github.com/ethereum/go-ethereum/accounts" @@ -296,6 +297,51 @@ func (s *suaveRuntime) doHTTPRequest(request types.HttpRequest) ([]byte, error) return data, nil } +// TODO: Non-aggregated error handling +func (s *suaveRuntime) doHTTPRequests(requests []types.HttpRequest) ([][]byte, error) { + var wg sync.WaitGroup + responses := make([][]byte, len(requests)) + errCh := make(chan error, len(requests)) + resCh := make(chan struct { + index int + resp []byte + }, len(requests)) + + for i, request := range requests { + wg.Add(1) + go func(i int, request types.HttpRequest) { + defer wg.Done() + resp, err := s.doHTTPRequest(request) + if err != nil { + errCh <- err + return + } + resCh <- struct { + index int + resp []byte + }{index: i, resp: resp} + }(i, request) + } + + go func() { + wg.Wait() + close(errCh) + close(resCh) + }() + + for err := range errCh { + if err != nil { + return nil, err + } + } + + for res := range resCh { + responses[res.index] = res.resp + } + + return responses, nil +} + func (s *suaveRuntime) resolveURL(urlOrServiceName string) (string, error) { var allowed bool // resolve dns if possible diff --git a/core/vm/contracts_suave_runtime_adapter.go b/core/vm/contracts_suave_runtime_adapter.go index c8ced1850..812fd07da 100644 --- a/core/vm/contracts_suave_runtime_adapter.go +++ b/core/vm/contracts_suave_runtime_adapter.go @@ -1,5 +1,5 @@ // Code generated by suave/gen. DO NOT EDIT. -// Hash: 58abede869b35f32efbb95ee4b2c2eff30631ae4ecb4f2732cd972174fe95ced +// Hash: 0f81d89c49fab4d406fc8b2116dee34a700fe51f246ba99c831af8be8975300e package vm import ( @@ -24,6 +24,7 @@ type SuaveRuntime interface { confidentialStore(dataId types.DataId, key string, value []byte) error contextGet(key string) ([]byte, error) doHTTPRequest(request types.HttpRequest) ([]byte, error) + doHTTPRequests(requests []types.HttpRequest) ([][]byte, error) ethcall(contractAddr common.Address, input1 []byte) ([]byte, error) extractHint(bundleData []byte) ([]byte, error) fetchDataRecords(cond uint64, namespace string) ([]types.DataRecord, error) @@ -48,6 +49,7 @@ var ( confidentialStoreAddr = common.HexToAddress("0x0000000000000000000000000000000042020000") contextGetAddr = common.HexToAddress("0x0000000000000000000000000000000053300003") doHTTPRequestAddr = common.HexToAddress("0x0000000000000000000000000000000043200002") + doHTTPRequestsAddr = common.HexToAddress("0x0000000000000000000000000000000043200003") ethcallAddr = common.HexToAddress("0x0000000000000000000000000000000042100003") extractHintAddr = common.HexToAddress("0x0000000000000000000000000000000042100037") fetchDataRecordsAddr = common.HexToAddress("0x0000000000000000000000000000000042030001") @@ -65,7 +67,7 @@ var ( ) var addrList = []common.Address{ - buildEthBlockAddr, buildEthBlockToAddr, confidentialInputsAddr, confidentialRetrieveAddr, confidentialStoreAddr, contextGetAddr, doHTTPRequestAddr, ethcallAddr, extractHintAddr, fetchDataRecordsAddr, fillMevShareBundleAddr, newBuilderAddr, newDataRecordAddr, privateKeyGenAddr, randomBytesAddr, signEthTransactionAddr, signMessageAddr, simulateBundleAddr, simulateTransactionAddr, submitBundleJsonRPCAddr, submitEthBlockToRelayAddr, + buildEthBlockAddr, buildEthBlockToAddr, confidentialInputsAddr, confidentialRetrieveAddr, confidentialStoreAddr, contextGetAddr, doHTTPRequestAddr, doHTTPRequestsAddr, ethcallAddr, extractHintAddr, fetchDataRecordsAddr, fillMevShareBundleAddr, newBuilderAddr, newDataRecordAddr, privateKeyGenAddr, randomBytesAddr, signEthTransactionAddr, signMessageAddr, simulateBundleAddr, simulateTransactionAddr, submitBundleJsonRPCAddr, submitEthBlockToRelayAddr, } type SuaveRuntimeAdapter struct { @@ -95,6 +97,9 @@ func (b *SuaveRuntimeAdapter) run(addr common.Address, input []byte) ([]byte, er case doHTTPRequestAddr: return b.doHTTPRequest(input) + case doHTTPRequestsAddr: + return b.doHTTPRequests(input) + case ethcallAddr: return b.ethcall(input) @@ -435,6 +440,47 @@ func (b *SuaveRuntimeAdapter) doHTTPRequest(input []byte) (res []byte, err error } +func (b *SuaveRuntimeAdapter) doHTTPRequests(input []byte) (res []byte, err error) { + var ( + unpacked []interface{} + result []byte + ) + + _ = unpacked + _ = result + + unpacked, err = artifacts.SuaveAbi.Methods["doHTTPRequests"].Inputs.Unpack(input) + if err != nil { + err = errFailedToUnpackInput + return + } + + var ( + requests []types.HttpRequest + ) + + if err = mapstructure.Decode(unpacked[0], &requests); err != nil { + err = errFailedToDecodeField + return + } + + var ( + httpResponses [][]byte + ) + + if httpResponses, err = b.impl.doHTTPRequests(requests); err != nil { + return + } + + result, err = artifacts.SuaveAbi.Methods["doHTTPRequests"].Outputs.Pack(httpResponses) + if err != nil { + err = errFailedToPackOutput + return + } + return result, nil + +} + func (b *SuaveRuntimeAdapter) ethcall(input []byte) (res []byte, err error) { var ( unpacked []interface{} diff --git a/core/vm/contracts_suave_runtime_adapter_test.go b/core/vm/contracts_suave_runtime_adapter_test.go index f7fb31124..f08216344 100644 --- a/core/vm/contracts_suave_runtime_adapter_test.go +++ b/core/vm/contracts_suave_runtime_adapter_test.go @@ -79,6 +79,12 @@ func (m *mockRuntime) doHTTPRequest(request types.HttpRequest) ([]byte, error) { return []byte{0x1}, nil } +func (m *mockRuntime) doHTTPRequests(request []types.HttpRequest) ([][]byte, error) { + var byteSlices [][]byte + byteSlices = append(byteSlices, []byte{0x1}) + return byteSlices, nil +} + func (m *mockRuntime) newBuilder() (string, error) { return "", nil } diff --git a/core/vm/contracts_suave_test.go b/core/vm/contracts_suave_test.go index 3702b0fa5..7dcf50241 100644 --- a/core/vm/contracts_suave_test.go +++ b/core/vm/contracts_suave_test.go @@ -3,6 +3,7 @@ package vm import ( "context" "math/big" + "fmt" "net/http" "net/http/httptest" "strings" @@ -293,6 +294,35 @@ func TestSuave_HttpRequest_Basic(t *testing.T) { } } +func TestSuave_HttpRequests_Basic(t *testing.T) { + srv := httptest.NewServer(&httpTestHandler{ + fn: basicHandler, + }) + + s := &suaveRuntime{ + suaveContext: &SuaveContext{ + Backend: &SuaveExecutionBackend{ + ExternalWhitelist: []string{"httpbin.org"}, + }, + }, + } + + defer srv.Close() + + var requests []types.HttpRequest + for i := 0; i < 3; i++ { + requests = append(requests, types.HttpRequest{Url: "https://httpbin.org/delay/1", Method: "GET"}) + } + + start := time.Now() + resp, err := s.doHTTPRequests(requests) + elapsed := time.Since(start) + require.NoError(t, err) + fmt.Println(resp) + + require.True(t, elapsed < 2*time.Second) +} + func TestSuave_HttpRequest_FlashbotsSignatue(t *testing.T) { signingKey, _ := crypto.GenerateKey() signingKeyAddr := crypto.PubkeyToAddress(signingKey.PublicKey).Hex() diff --git a/suave/artifacts/SuaveLib.json b/suave/artifacts/SuaveLib.json index 9dfc12a26..55e8de84c 100644 --- a/suave/artifacts/SuaveLib.json +++ b/suave/artifacts/SuaveLib.json @@ -1 +1 @@ -[{"type":"error","name":"PeekerReverted","inputs":[{"name":"addr","type":"address"},{"name":"err","type":"bytes"}]},{"type":"function","name":"buildEthBlock","inputs":[{"name":"blockArgs","type":"tuple","internalType":"struct Suave.BuildBlockArgs","components":[{"name":"slot","type":"uint64","internalType":"uint64"},{"name":"proposerPubkey","type":"bytes","internalType":"bytes"},{"name":"parent","type":"bytes32","internalType":"bytes32"},{"name":"timestamp","type":"uint64","internalType":"uint64"},{"name":"feeRecipient","type":"address","internalType":"address"},{"name":"gasLimit","type":"uint64","internalType":"uint64"},{"name":"random","type":"bytes32","internalType":"bytes32"},{"name":"withdrawals","type":"tuple[]","internalType":"struct Suave.Withdrawal[]","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"validator","type":"uint64","internalType":"uint64"},{"name":"Address","type":"address","internalType":"address"},{"name":"amount","type":"uint64","internalType":"uint64"}]},{"name":"extra","type":"bytes","internalType":"bytes"},{"name":"beaconRoot","type":"bytes32","internalType":"bytes32"},{"name":"fillPending","type":"bool","internalType":"bool"}]},{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"relayUrl","type":"string","internalType":"string"}],"outputs":[{"name":"blockBid","type":"bytes","internalType":"bytes"},{"name":"executionPayload","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"buildEthBlockTo","inputs":[{"name":"executionNodeURL","type":"string","internalType":"string"},{"name":"blockArgs","type":"tuple","internalType":"struct Suave.BuildBlockArgs","components":[{"name":"slot","type":"uint64","internalType":"uint64"},{"name":"proposerPubkey","type":"bytes","internalType":"bytes"},{"name":"parent","type":"bytes32","internalType":"bytes32"},{"name":"timestamp","type":"uint64","internalType":"uint64"},{"name":"feeRecipient","type":"address","internalType":"address"},{"name":"gasLimit","type":"uint64","internalType":"uint64"},{"name":"random","type":"bytes32","internalType":"bytes32"},{"name":"withdrawals","type":"tuple[]","internalType":"struct Suave.Withdrawal[]","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"validator","type":"uint64","internalType":"uint64"},{"name":"Address","type":"address","internalType":"address"},{"name":"amount","type":"uint64","internalType":"uint64"}]},{"name":"extra","type":"bytes","internalType":"bytes"},{"name":"beaconRoot","type":"bytes32","internalType":"bytes32"},{"name":"fillPending","type":"bool","internalType":"bool"}]},{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"relayUrl","type":"string","internalType":"string"}],"outputs":[{"name":"blockBid","type":"bytes","internalType":"bytes"},{"name":"executionPayload","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"confidentialInputs","outputs":[{"name":"confindentialData","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"confidentialRetrieve","inputs":[{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"key","type":"string","internalType":"string"}],"outputs":[{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"confidentialStore","inputs":[{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"key","type":"string","internalType":"string"},{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"contextGet","inputs":[{"name":"key","type":"string","internalType":"string"}],"outputs":[{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"doHTTPRequest","inputs":[{"name":"request","type":"tuple","internalType":"struct Suave.HttpRequest","components":[{"name":"url","type":"string","internalType":"string"},{"name":"method","type":"string","internalType":"string"},{"name":"headers","type":"string[]","internalType":"string[]"},{"name":"body","type":"bytes","internalType":"bytes"},{"name":"withFlashbotsSignature","type":"bool","internalType":"bool"},{"name":"timeout","type":"uint64","internalType":"uint64"}]}],"outputs":[{"name":"httpResponse","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"ethcall","inputs":[{"name":"contractAddr","type":"address","internalType":"address"},{"name":"input1","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"callOutput","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"extractHint","inputs":[{"name":"bundleData","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"hints","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"fetchDataRecords","inputs":[{"name":"cond","type":"uint64","internalType":"uint64"},{"name":"namespace","type":"string","internalType":"string"}],"outputs":[{"name":"dataRecords","type":"tuple[]","internalType":"struct Suave.DataRecord[]","components":[{"name":"id","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"salt","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"decryptionCondition","type":"uint64","internalType":"uint64"},{"name":"allowedPeekers","type":"address[]","internalType":"address[]"},{"name":"allowedStores","type":"address[]","internalType":"address[]"},{"name":"version","type":"string","internalType":"string"}]}]},{"type":"function","name":"fillMevShareBundle","inputs":[{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"}],"outputs":[{"name":"encodedBundle","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"newBuilder","outputs":[{"name":"sessionid","type":"string","internalType":"string"}]},{"type":"function","name":"newDataRecord","inputs":[{"name":"decryptionCondition","type":"uint64","internalType":"uint64"},{"name":"allowedPeekers","type":"address[]","internalType":"address[]"},{"name":"allowedStores","type":"address[]","internalType":"address[]"},{"name":"dataType","type":"string","internalType":"string"}],"outputs":[{"name":"dataRecord","type":"tuple","internalType":"struct Suave.DataRecord","components":[{"name":"id","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"salt","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"decryptionCondition","type":"uint64","internalType":"uint64"},{"name":"allowedPeekers","type":"address[]","internalType":"address[]"},{"name":"allowedStores","type":"address[]","internalType":"address[]"},{"name":"version","type":"string","internalType":"string"}]}]},{"type":"function","name":"privateKeyGen","inputs":[{"name":"crypto","type":"uint8","internalType":"struct Suave.CryptoSignature"}],"outputs":[{"name":"privateKey","type":"string","internalType":"string"}]},{"type":"function","name":"randomBytes","inputs":[{"name":"numBytes","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"signEthTransaction","inputs":[{"name":"txn","type":"bytes","internalType":"bytes"},{"name":"chainId","type":"string","internalType":"string"},{"name":"signingKey","type":"string","internalType":"string"}],"outputs":[{"name":"signedTxn","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"signMessage","inputs":[{"name":"digest","type":"bytes","internalType":"bytes"},{"name":"crypto","type":"uint8","internalType":"struct Suave.CryptoSignature"},{"name":"signingKey","type":"string","internalType":"string"}],"outputs":[{"name":"signature","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"simulateBundle","inputs":[{"name":"bundleData","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"effectiveGasPrice","type":"uint64","internalType":"uint64"}]},{"type":"function","name":"simulateTransaction","inputs":[{"name":"sessionid","type":"string","internalType":"string"},{"name":"txn","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"simulationResult","type":"tuple","internalType":"struct Suave.SimulateTransactionResult","components":[{"name":"egp","type":"uint64","internalType":"uint64"},{"name":"logs","type":"tuple[]","internalType":"struct Suave.SimulatedLog[]","components":[{"name":"data","type":"bytes","internalType":"bytes"},{"name":"addr","type":"address","internalType":"address"},{"name":"topics","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"success","type":"bool","internalType":"bool"},{"name":"error","type":"string","internalType":"string"}]}]},{"type":"function","name":"submitBundleJsonRPC","inputs":[{"name":"url","type":"string","internalType":"string"},{"name":"method","type":"string","internalType":"string"},{"name":"params","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"errorMessage","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"submitEthBlockToRelay","inputs":[{"name":"relayUrl","type":"string","internalType":"string"},{"name":"builderBid","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"blockBid","type":"bytes","internalType":"bytes"}]}] \ No newline at end of file +[{"type":"error","name":"PeekerReverted","inputs":[{"name":"addr","type":"address"},{"name":"err","type":"bytes"}]},{"type":"function","name":"buildEthBlock","inputs":[{"name":"blockArgs","type":"tuple","internalType":"struct Suave.BuildBlockArgs","components":[{"name":"slot","type":"uint64","internalType":"uint64"},{"name":"proposerPubkey","type":"bytes","internalType":"bytes"},{"name":"parent","type":"bytes32","internalType":"bytes32"},{"name":"timestamp","type":"uint64","internalType":"uint64"},{"name":"feeRecipient","type":"address","internalType":"address"},{"name":"gasLimit","type":"uint64","internalType":"uint64"},{"name":"random","type":"bytes32","internalType":"bytes32"},{"name":"withdrawals","type":"tuple[]","internalType":"struct Suave.Withdrawal[]","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"validator","type":"uint64","internalType":"uint64"},{"name":"Address","type":"address","internalType":"address"},{"name":"amount","type":"uint64","internalType":"uint64"}]},{"name":"extra","type":"bytes","internalType":"bytes"},{"name":"beaconRoot","type":"bytes32","internalType":"bytes32"},{"name":"fillPending","type":"bool","internalType":"bool"}]},{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"relayUrl","type":"string","internalType":"string"}],"outputs":[{"name":"blockBid","type":"bytes","internalType":"bytes"},{"name":"executionPayload","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"buildEthBlockTo","inputs":[{"name":"executionNodeURL","type":"string","internalType":"string"},{"name":"blockArgs","type":"tuple","internalType":"struct Suave.BuildBlockArgs","components":[{"name":"slot","type":"uint64","internalType":"uint64"},{"name":"proposerPubkey","type":"bytes","internalType":"bytes"},{"name":"parent","type":"bytes32","internalType":"bytes32"},{"name":"timestamp","type":"uint64","internalType":"uint64"},{"name":"feeRecipient","type":"address","internalType":"address"},{"name":"gasLimit","type":"uint64","internalType":"uint64"},{"name":"random","type":"bytes32","internalType":"bytes32"},{"name":"withdrawals","type":"tuple[]","internalType":"struct Suave.Withdrawal[]","components":[{"name":"index","type":"uint64","internalType":"uint64"},{"name":"validator","type":"uint64","internalType":"uint64"},{"name":"Address","type":"address","internalType":"address"},{"name":"amount","type":"uint64","internalType":"uint64"}]},{"name":"extra","type":"bytes","internalType":"bytes"},{"name":"beaconRoot","type":"bytes32","internalType":"bytes32"},{"name":"fillPending","type":"bool","internalType":"bool"}]},{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"relayUrl","type":"string","internalType":"string"}],"outputs":[{"name":"blockBid","type":"bytes","internalType":"bytes"},{"name":"executionPayload","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"confidentialInputs","outputs":[{"name":"confindentialData","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"confidentialRetrieve","inputs":[{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"key","type":"string","internalType":"string"}],"outputs":[{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"confidentialStore","inputs":[{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"key","type":"string","internalType":"string"},{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"contextGet","inputs":[{"name":"key","type":"string","internalType":"string"}],"outputs":[{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"doHTTPRequest","inputs":[{"name":"request","type":"tuple","internalType":"struct Suave.HttpRequest","components":[{"name":"url","type":"string","internalType":"string"},{"name":"method","type":"string","internalType":"string"},{"name":"headers","type":"string[]","internalType":"string[]"},{"name":"body","type":"bytes","internalType":"bytes"},{"name":"withFlashbotsSignature","type":"bool","internalType":"bool"},{"name":"timeout","type":"uint64","internalType":"uint64"}]}],"outputs":[{"name":"httpResponse","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"doHTTPRequests","inputs":[{"name":"requests","type":"tuple[]","internalType":"struct Suave.HttpRequest[]","components":[{"name":"url","type":"string","internalType":"string"},{"name":"method","type":"string","internalType":"string"},{"name":"headers","type":"string[]","internalType":"string[]"},{"name":"body","type":"bytes","internalType":"bytes"},{"name":"withFlashbotsSignature","type":"bool","internalType":"bool"},{"name":"timeout","type":"uint64","internalType":"uint64"}]}],"outputs":[{"name":"httpResponses","type":"bytes[]","internalType":"bytes[]"}]},{"type":"function","name":"ethcall","inputs":[{"name":"contractAddr","type":"address","internalType":"address"},{"name":"input1","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"callOutput","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"extractHint","inputs":[{"name":"bundleData","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"hints","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"fetchDataRecords","inputs":[{"name":"cond","type":"uint64","internalType":"uint64"},{"name":"namespace","type":"string","internalType":"string"}],"outputs":[{"name":"dataRecords","type":"tuple[]","internalType":"struct Suave.DataRecord[]","components":[{"name":"id","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"salt","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"decryptionCondition","type":"uint64","internalType":"uint64"},{"name":"allowedPeekers","type":"address[]","internalType":"address[]"},{"name":"allowedStores","type":"address[]","internalType":"address[]"},{"name":"version","type":"string","internalType":"string"}]}]},{"type":"function","name":"fillMevShareBundle","inputs":[{"name":"dataId","type":"bytes16","internalType":"struct Suave.DataId"}],"outputs":[{"name":"encodedBundle","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"newBuilder","outputs":[{"name":"sessionid","type":"string","internalType":"string"}]},{"type":"function","name":"newDataRecord","inputs":[{"name":"decryptionCondition","type":"uint64","internalType":"uint64"},{"name":"allowedPeekers","type":"address[]","internalType":"address[]"},{"name":"allowedStores","type":"address[]","internalType":"address[]"},{"name":"dataType","type":"string","internalType":"string"}],"outputs":[{"name":"dataRecord","type":"tuple","internalType":"struct Suave.DataRecord","components":[{"name":"id","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"salt","type":"bytes16","internalType":"struct Suave.DataId"},{"name":"decryptionCondition","type":"uint64","internalType":"uint64"},{"name":"allowedPeekers","type":"address[]","internalType":"address[]"},{"name":"allowedStores","type":"address[]","internalType":"address[]"},{"name":"version","type":"string","internalType":"string"}]}]},{"type":"function","name":"privateKeyGen","inputs":[{"name":"crypto","type":"uint8","internalType":"struct Suave.CryptoSignature"}],"outputs":[{"name":"privateKey","type":"string","internalType":"string"}]},{"type":"function","name":"randomBytes","inputs":[{"name":"numBytes","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"value","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"signEthTransaction","inputs":[{"name":"txn","type":"bytes","internalType":"bytes"},{"name":"chainId","type":"string","internalType":"string"},{"name":"signingKey","type":"string","internalType":"string"}],"outputs":[{"name":"signedTxn","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"signMessage","inputs":[{"name":"digest","type":"bytes","internalType":"bytes"},{"name":"crypto","type":"uint8","internalType":"struct Suave.CryptoSignature"},{"name":"signingKey","type":"string","internalType":"string"}],"outputs":[{"name":"signature","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"simulateBundle","inputs":[{"name":"bundleData","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"effectiveGasPrice","type":"uint64","internalType":"uint64"}]},{"type":"function","name":"simulateTransaction","inputs":[{"name":"sessionid","type":"string","internalType":"string"},{"name":"txn","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"simulationResult","type":"tuple","internalType":"struct Suave.SimulateTransactionResult","components":[{"name":"egp","type":"uint64","internalType":"uint64"},{"name":"logs","type":"tuple[]","internalType":"struct Suave.SimulatedLog[]","components":[{"name":"data","type":"bytes","internalType":"bytes"},{"name":"addr","type":"address","internalType":"address"},{"name":"topics","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"success","type":"bool","internalType":"bool"},{"name":"error","type":"string","internalType":"string"}]}]},{"type":"function","name":"submitBundleJsonRPC","inputs":[{"name":"url","type":"string","internalType":"string"},{"name":"method","type":"string","internalType":"string"},{"name":"params","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"errorMessage","type":"bytes","internalType":"bytes"}]},{"type":"function","name":"submitEthBlockToRelay","inputs":[{"name":"relayUrl","type":"string","internalType":"string"},{"name":"builderBid","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"blockBid","type":"bytes","internalType":"bytes"}]}] \ No newline at end of file diff --git a/suave/artifacts/addresses.go b/suave/artifacts/addresses.go index a2c83e423..9df44ecdc 100644 --- a/suave/artifacts/addresses.go +++ b/suave/artifacts/addresses.go @@ -1,5 +1,5 @@ // Code generated by suave/gen. DO NOT EDIT. -// Hash: 58abede869b35f32efbb95ee4b2c2eff30631ae4ecb4f2732cd972174fe95ced +// Hash: 0f81d89c49fab4d406fc8b2116dee34a700fe51f246ba99c831af8be8975300e package artifacts import ( @@ -15,6 +15,7 @@ var ( confidentialStoreAddr = common.HexToAddress("0x0000000000000000000000000000000042020000") contextGetAddr = common.HexToAddress("0x0000000000000000000000000000000053300003") doHTTPRequestAddr = common.HexToAddress("0x0000000000000000000000000000000043200002") + doHTTPRequestsAddr = common.HexToAddress("0x0000000000000000000000000000000043200003") ethcallAddr = common.HexToAddress("0x0000000000000000000000000000000042100003") extractHintAddr = common.HexToAddress("0x0000000000000000000000000000000042100037") fetchDataRecordsAddr = common.HexToAddress("0x0000000000000000000000000000000042030001") @@ -39,6 +40,7 @@ var SuaveMethods = map[string]common.Address{ "confidentialStore": confidentialStoreAddr, "contextGet": contextGetAddr, "doHTTPRequest": doHTTPRequestAddr, + "doHTTPRequests": doHTTPRequestsAddr, "ethcall": ethcallAddr, "extractHint": extractHintAddr, "fetchDataRecords": fetchDataRecordsAddr, @@ -71,6 +73,8 @@ func PrecompileAddressToName(addr common.Address) string { return "contextGet" case doHTTPRequestAddr: return "doHTTPRequest" + case doHTTPRequestsAddr: + return "doHTTPRequests" case ethcallAddr: return "ethcall" case extractHintAddr: diff --git a/suave/gen/suave_spec.yaml b/suave/gen/suave_spec.yaml index e9abe3b70..f7c59df20 100644 --- a/suave/gen/suave_spec.yaml +++ b/suave/gen/suave_spec.yaml @@ -386,6 +386,18 @@ functions: - name: httpResponse type: bytes description: "Body of the response" + - name: doHTTPRequests + address: "0x0000000000000000000000000000000043200003" + description: "Executes multiple `doHTTPRequest`s async" + input: + - name: requests + type: HttpRequest[] + description: "Requests to perform" + output: + fields: + - name: httpResponses + type: bytes[] + description: "Body of the responses" - name: newBuilder address: "0x0000000000000000000000000000000053200001" description: "Initializes a new remote builder session" diff --git a/suave/sol/libraries/Suave.sol b/suave/sol/libraries/Suave.sol index 4a6977798..d18ce17c7 100644 --- a/suave/sol/libraries/Suave.sol +++ b/suave/sol/libraries/Suave.sol @@ -122,6 +122,8 @@ library Suave { address public constant DO_HTTPREQUEST = 0x0000000000000000000000000000000043200002; + address public constant DO_HTTPREQUESTS = 0x0000000000000000000000000000000043200003; + address public constant ETHCALL = 0x0000000000000000000000000000000042100003; address public constant EXTRACT_HINT = 0x0000000000000000000000000000000042100037; @@ -264,6 +266,18 @@ library Suave { return abi.decode(data, (bytes)); } + /// @notice Executes multiple `doHTTPRequest`s async + /// @param requests Requests to perform + /// @return httpResponses Body of the responses + function doHTTPRequests(HttpRequest[] memory requests) internal returns (bytes[] memory) { + (bool success, bytes memory data) = DO_HTTPREQUESTS.call(abi.encode(requests)); + if (!success) { + revert PeekerReverted(DO_HTTPREQUESTS, data); + } + + return abi.decode(data, (bytes[])); + } + /// @notice Uses the `eth_call` JSON RPC method to let you simulate a function call and return the response. /// @param contractAddr Address of the contract to call /// @param input1 Data to send to the contract