diff --git a/core/types/suave_structs.go b/core/types/suave_structs.go index 4f27df31f..8e3e3c2b3 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: 7a53bc3490ced97366af883bb45a9dce2d5dcdcaa93dc61171d9940706691299 +// Hash: facdf7b710eb48ea73a1e73caa24bb40336de9168fbacbe84bdc7403760b8880 package types import "github.com/ethereum/go-ethereum/common" diff --git a/core/vm/contracts_suave.go b/core/vm/contracts_suave.go index 12409fe6a..a366c8a48 100644 --- a/core/vm/contracts_suave.go +++ b/core/vm/contracts_suave.go @@ -223,30 +223,11 @@ func (s *suaveRuntime) doHTTPRequest(request types.HttpRequest) ([]byte, error) body = bytes.NewReader(request.Body) } - var allowed bool - // resolve dns if possible - if endpoint, ok := s.suaveContext.Backend.ServiceAliasRegistry[request.Url]; ok { - request.Url = endpoint - } else { - // decode the url and check if the domain is allowed - parsedURL, err := url.Parse(request.Url) - if err != nil { - panic(err) - } - - // check if the domain is allowed - for _, allowedDomain := range s.suaveContext.Backend.ExternalWhitelist { - if allowedDomain == "*" || allowedDomain == parsedURL.Hostname() { - allowed = true - break - } - } - if !allowed { - return nil, fmt.Errorf("domain %s is not allowed", parsedURL.Hostname()) - } + url, err := s.resolveURL(request.Url) + if err != nil { + return nil, err } - - req, err := http.NewRequest(request.Method, request.Url, body) + req, err := http.NewRequest(request.Method, url, body) if err != nil { return nil, err } @@ -291,6 +272,33 @@ func (s *suaveRuntime) doHTTPRequest(request types.HttpRequest) ([]byte, error) return data, nil } +func (s *suaveRuntime) resolveURL(urlOrServiceName string) (string, error) { + var allowed bool + // resolve dns if possible + if endpoint, ok := s.suaveContext.Backend.ServiceAliasRegistry[urlOrServiceName]; ok { + return endpoint, nil + } + + // decode the url and check if the domain is allowed + parsedURL, err := url.Parse(urlOrServiceName) + if err != nil { + return "", err + } + + // check if the domain is allowed + for _, allowedDomain := range s.suaveContext.Backend.ExternalWhitelist { + if allowedDomain == "*" || allowedDomain == parsedURL.Hostname() { + allowed = true + break + } + } + if !allowed { + return "", fmt.Errorf("domain %s is not allowed", parsedURL.Hostname()) + } + + return urlOrServiceName, nil +} + func (s *suaveRuntime) newBuilder() (string, error) { return s.suaveContext.Backend.ConfidentialEthBackend.NewSession(context.Background()) } diff --git a/core/vm/contracts_suave_eth.go b/core/vm/contracts_suave_eth.go index 5ee3dd129..094323302 100644 --- a/core/vm/contracts_suave_eth.go +++ b/core/vm/contracts_suave_eth.go @@ -18,6 +18,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + suave_backends "github.com/ethereum/go-ethereum/suave/backends" + suave "github.com/ethereum/go-ethereum/suave/core" "github.com/flashbots/go-boost-utils/bls" "github.com/flashbots/go-boost-utils/ssz" "github.com/holiman/uint256" @@ -113,8 +115,12 @@ func (b *suaveRuntime) ethcall(contractAddr common.Address, input []byte) ([]byt return b.suaveContext.Backend.ConfidentialEthBackend.Call(context.Background(), contractAddr, input) } -// This is a temp solution and will be replaced with block building session func (b *suaveRuntime) buildEthBlock(blockArgs types.BuildBlockArgs, dataID types.DataId, relayUrl string) ([]byte, []byte, error) { + return b.buildEthBlockTo("", blockArgs, dataID, relayUrl) +} + +// This is a temp solution and will be replaced with block building session +func (b *suaveRuntime) buildEthBlockTo(execNode string, blockArgs types.BuildBlockArgs, dataID types.DataId, relayUrl string) ([]byte, []byte, error) { dataIDs := [][16]byte{} // first check for merged record, else assume regular record if mergedDataRecordsBytes, err := b.suaveContext.Backend.ConfidentialStore.Retrieve(dataID, buildEthBlockAddr, "default:v0:mergedDataRecords"); err == nil { @@ -214,8 +220,20 @@ func (b *suaveRuntime) buildEthBlock(blockArgs types.BuildBlockArgs, dataID type log.Info("requesting a block be built", "mergedBundles", mergedBundles) - envelope, err := b.suaveContext.Backend.ConfidentialEthBackend.BuildEthBlockFromBundles(context.TODO(), &blockArgs, mergedBundles) + var confBackend suave.ConfidentialEthBackend + if execNode == "" { + // Use the backend configured with --suave.eth.remote-endpoint + confBackend = b.suaveContext.Backend.ConfidentialEthBackend + } else { + // Resolve the url from the execNode + url, err := b.resolveURL(execNode) + if err != nil { + return nil, nil, err + } + confBackend = suave_backends.NewRemoteEthBackend(url) + } + envelope, err := confBackend.BuildEthBlockFromBundles(context.TODO(), &blockArgs, mergedBundles) if err != nil { return nil, nil, fmt.Errorf("could not build eth block: %w", err) } diff --git a/core/vm/contracts_suave_runtime_adapter.go b/core/vm/contracts_suave_runtime_adapter.go index 705b81499..607abc468 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: 7a53bc3490ced97366af883bb45a9dce2d5dcdcaa93dc61171d9940706691299 +// Hash: facdf7b710eb48ea73a1e73caa24bb40336de9168fbacbe84bdc7403760b8880 package vm import ( @@ -18,6 +18,7 @@ var ( type SuaveRuntime interface { buildEthBlock(blockArgs types.BuildBlockArgs, dataId types.DataId, relayUrl string) ([]byte, []byte, error) + buildEthBlockTo(executionNodeURL string, blockArgs types.BuildBlockArgs, dataId types.DataId, relayUrl string) ([]byte, []byte, error) confidentialInputs() ([]byte, error) confidentialRetrieve(dataId types.DataId, key string) ([]byte, error) confidentialStore(dataId types.DataId, key string, value []byte) error @@ -41,6 +42,7 @@ type SuaveRuntime interface { var ( buildEthBlockAddr = common.HexToAddress("0x0000000000000000000000000000000042100001") + buildEthBlockToAddr = common.HexToAddress("0x0000000000000000000000000000000042100006") confidentialInputsAddr = common.HexToAddress("0x0000000000000000000000000000000042010001") confidentialRetrieveAddr = common.HexToAddress("0x0000000000000000000000000000000042020001") confidentialStoreAddr = common.HexToAddress("0x0000000000000000000000000000000042020000") @@ -63,7 +65,7 @@ var ( ) var addrList = []common.Address{ - buildEthBlockAddr, 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, ethcallAddr, extractHintAddr, fetchDataRecordsAddr, fillMevShareBundleAddr, newBuilderAddr, newDataRecordAddr, privateKeyGenAddr, randomBytesAddr, signEthTransactionAddr, signMessageAddr, simulateBundleAddr, simulateTransactionAddr, submitBundleJsonRPCAddr, submitEthBlockToRelayAddr, } type SuaveRuntimeAdapter struct { @@ -75,6 +77,9 @@ func (b *SuaveRuntimeAdapter) run(addr common.Address, input []byte) ([]byte, er case buildEthBlockAddr: return b.buildEthBlock(input) + case buildEthBlockToAddr: + return b.buildEthBlockTo(input) + case confidentialInputsAddr: return b.confidentialInputs(input) @@ -188,6 +193,60 @@ func (b *SuaveRuntimeAdapter) buildEthBlock(input []byte) (res []byte, err error } +func (b *SuaveRuntimeAdapter) buildEthBlockTo(input []byte) (res []byte, err error) { + var ( + unpacked []interface{} + result []byte + ) + + _ = unpacked + _ = result + + unpacked, err = artifacts.SuaveAbi.Methods["buildEthBlockTo"].Inputs.Unpack(input) + if err != nil { + err = errFailedToUnpackInput + return + } + + var ( + executionNodeURL string + blockArgs types.BuildBlockArgs + dataId types.DataId + relayUrl string + ) + + executionNodeURL = unpacked[0].(string) + + if err = mapstructure.Decode(unpacked[1], &blockArgs); err != nil { + err = errFailedToDecodeField + return + } + + if err = mapstructure.Decode(unpacked[2], &dataId); err != nil { + err = errFailedToDecodeField + return + } + + relayUrl = unpacked[3].(string) + + var ( + blockBid []byte + executionPayload []byte + ) + + if blockBid, executionPayload, err = b.impl.buildEthBlockTo(executionNodeURL, blockArgs, dataId, relayUrl); err != nil { + return + } + + result, err = artifacts.SuaveAbi.Methods["buildEthBlockTo"].Outputs.Pack(blockBid, executionPayload) + if err != nil { + err = errFailedToPackOutput + return + } + return result, nil + +} + func (b *SuaveRuntimeAdapter) confidentialInputs(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 d6101119a..f7fb31124 100644 --- a/core/vm/contracts_suave_runtime_adapter_test.go +++ b/core/vm/contracts_suave_runtime_adapter_test.go @@ -15,6 +15,10 @@ var _ SuaveRuntime = &mockRuntime{} type mockRuntime struct { } +func (m *mockRuntime) buildEthBlockTo(execNode string, blockArgs types.BuildBlockArgs, dataID types.DataId, relayUrl string) ([]byte, []byte, error) { + return nil, nil, nil +} + func (m *mockRuntime) buildEthBlock(blockArgs types.BuildBlockArgs, dataId types.DataId, namespace string) ([]byte, []byte, error) { return []byte{0x1}, []byte{0x1}, nil } diff --git a/suave/artifacts/SuaveLib.json b/suave/artifacts/SuaveLib.json index aa6b9a2d4..39c502ff9 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":"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"}]}],"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"}]}],"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 diff --git a/suave/artifacts/addresses.go b/suave/artifacts/addresses.go index b22bf0144..53669f528 100644 --- a/suave/artifacts/addresses.go +++ b/suave/artifacts/addresses.go @@ -1,5 +1,5 @@ // Code generated by suave/gen. DO NOT EDIT. -// Hash: 7a53bc3490ced97366af883bb45a9dce2d5dcdcaa93dc61171d9940706691299 +// Hash: facdf7b710eb48ea73a1e73caa24bb40336de9168fbacbe84bdc7403760b8880 package artifacts import ( @@ -9,6 +9,7 @@ import ( // List of suave precompile addresses var ( buildEthBlockAddr = common.HexToAddress("0x0000000000000000000000000000000042100001") + buildEthBlockToAddr = common.HexToAddress("0x0000000000000000000000000000000042100006") confidentialInputsAddr = common.HexToAddress("0x0000000000000000000000000000000042010001") confidentialRetrieveAddr = common.HexToAddress("0x0000000000000000000000000000000042020001") confidentialStoreAddr = common.HexToAddress("0x0000000000000000000000000000000042020000") @@ -32,6 +33,7 @@ var ( var SuaveMethods = map[string]common.Address{ "buildEthBlock": buildEthBlockAddr, + "buildEthBlockTo": buildEthBlockToAddr, "confidentialInputs": confidentialInputsAddr, "confidentialRetrieve": confidentialRetrieveAddr, "confidentialStore": confidentialStoreAddr, @@ -57,6 +59,8 @@ func PrecompileAddressToName(addr common.Address) string { switch addr { case buildEthBlockAddr: return "buildEthBlock" + case buildEthBlockToAddr: + return "buildEthBlockTo" case confidentialInputsAddr: return "confidentialInputs" case confidentialRetrieveAddr: diff --git a/suave/gen/suave_spec.yaml b/suave/gen/suave_spec.yaml index c335fd2ec..81fce568c 100644 --- a/suave/gen/suave_spec.yaml +++ b/suave/gen/suave_spec.yaml @@ -262,6 +262,30 @@ functions: - name: executionPayload type: bytes description: "Execution payload encoded in JSON" + - name: buildEthBlockTo + address: "0x0000000000000000000000000000000042100006" + description: "Constructs an Ethereum block based on the provided data records. No blobs are returned." + input: + - name: executionNodeURL + type: string + description: "URL (or service name) of the execution node" + - name: blockArgs + type: BuildBlockArgs + description: "Arguments to build the block" + - name: dataId + type: DataId + description: "ID of the data record with mev-share bundle data" + - name: relayUrl + type: string + description: "If specified the built block will be submitted to the relay" + output: + fields: + - name: blockBid + type: bytes + description: "Block Bid encoded in JSON" + - name: executionPayload + type: bytes + description: "Execution payload encoded in JSON" - name: submitEthBlockToRelay address: "0x0000000000000000000000000000000042100002" description: "Submits a given builderBid to a mev-boost relay." diff --git a/suave/sol/libraries/Suave.sol b/suave/sol/libraries/Suave.sol index 7bc111782..ee2d46fa9 100644 --- a/suave/sol/libraries/Suave.sol +++ b/suave/sol/libraries/Suave.sol @@ -108,6 +108,8 @@ library Suave { address public constant BUILD_ETH_BLOCK = 0x0000000000000000000000000000000042100001; + address public constant BUILD_ETH_BLOCK_TO = 0x0000000000000000000000000000000042100006; + address public constant CONFIDENTIAL_INPUTS = 0x0000000000000000000000000000000042010001; address public constant CONFIDENTIAL_RETRIEVE = 0x0000000000000000000000000000000042020001; @@ -179,6 +181,28 @@ library Suave { return abi.decode(data, (bytes, bytes)); } + /// @notice Constructs an Ethereum block based on the provided data records. No blobs are returned. + /// @param executionNodeURL URL (or service name) of the execution node + /// @param blockArgs Arguments to build the block + /// @param dataId ID of the data record with mev-share bundle data + /// @param relayUrl If specified the built block will be submitted to the relay + /// @return blockBid Block Bid encoded in JSON + /// @return executionPayload Execution payload encoded in JSON + function buildEthBlockTo( + string memory executionNodeURL, + BuildBlockArgs memory blockArgs, + DataId dataId, + string memory relayUrl + ) internal returns (bytes memory, bytes memory) { + (bool success, bytes memory data) = + BUILD_ETH_BLOCK_TO.call(abi.encode(executionNodeURL, blockArgs, dataId, relayUrl)); + if (!success) { + revert PeekerReverted(BUILD_ETH_BLOCK_TO, data); + } + + return abi.decode(data, (bytes, bytes)); + } + /// @notice Provides the confidential inputs associated with a confidential computation request. Outputs are in bytes format. /// @return confindentialData Confidential inputs function confidentialInputs() internal returns (bytes memory) {