Skip to content

Commit

Permalink
Unifies bid allow peeker checks, implements an address that functions…
Browse files Browse the repository at this point in the history
… as allow all
  • Loading branch information
Ruteri committed Oct 25, 2023
1 parent a9c166c commit 9e77af3
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 39 deletions.
37 changes: 13 additions & 24 deletions core/vm/contracts_suave.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
suave "github.com/ethereum/go-ethereum/suave/core"
)
Expand Down Expand Up @@ -118,25 +117,21 @@ func (c *confStoreStore) RunConfidential(suaveContext *SuaveContext, input []byt
}

func (c *confStoreStore) runImpl(suaveContext *SuaveContext, bidId suave.BidId, key string, data []byte) error {
if len(suaveContext.CallerStack) == 0 {
return errors.New("not allowed in this suaveContext")
bid, err := suaveContext.Backend.ConfidentialStore.FetchBidById(bidId)
if err != nil {
return suave.ErrBidNotFound
}

// Can be zeroes in some fringe cases!
var caller common.Address
for i := len(suaveContext.CallerStack) - 1; i >= 0; i-- {
// Most recent non-nil non-this caller
if _c := suaveContext.CallerStack[i]; _c != nil && *_c != confStoreStoreAddress {
caller = *_c
break
}
caller, err := checkIsPrecompileCallAllowed(suaveContext, confStoreStoreAddress, bid)
if err != nil {
return err
}

if metrics.Enabled {
confStorePrecompileStoreMeter.Mark(int64(len(data)))
}

_, err := suaveContext.Backend.ConfidentialStore.Store(bidId, caller, key, data)
_, err = suaveContext.Backend.ConfidentialStore.Store(bidId, caller, key, data)
if err != nil {
return err
}
Expand Down Expand Up @@ -179,20 +174,14 @@ func (c *confStoreRetrieve) RunConfidential(suaveContext *SuaveContext, input []
}

func (c *confStoreRetrieve) runImpl(suaveContext *SuaveContext, bidId suave.BidId, key string) ([]byte, error) {
if len(suaveContext.CallerStack) == 0 {
return nil, errors.New("not allowed in this suaveContext")
bid, err := suaveContext.Backend.ConfidentialStore.FetchBidById(bidId)
if err != nil {
return nil, suave.ErrBidNotFound
}

log.Info("confStoreRetrieve", "bidId", bidId, "key", key)

// Can be zeroes in some fringe cases!
var caller common.Address
for i := len(suaveContext.CallerStack) - 1; i >= 0; i-- {
// Most recent non-nil non-this caller
if _c := suaveContext.CallerStack[i]; _c != nil && *_c != confStoreRetrieveAddress {
caller = *_c
break
}
caller, err := checkIsPrecompileCallAllowed(suaveContext, confStoreRetrieveAddress, bid)
if err != nil {
return nil, err
}

data, err := suaveContext.Backend.ConfidentialStore.Retrieve(bidId, caller, key)
Expand Down
5 changes: 5 additions & 0 deletions core/vm/contracts_suave_eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ func (c *buildEthBlock) runImpl(suaveContext *SuaveContext, blockArgs types.Buil
if err != nil {
return nil, nil, fmt.Errorf("could not fetch bid id %v: %w", bidId, err)
}

if _, err := checkIsPrecompileCallAllowed(suaveContext, buildEthBlockAddress, bid); err != nil {
return nil, nil, err
}

bidsToMerge[i] = bid.ToInnerBid()
}

Expand Down
3 changes: 3 additions & 0 deletions core/vm/contracts_suave_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ func TestSuavePrecompileStub(t *testing.T) {
// error in 'buildEthBlock' when it expects to retrieve bids in abi format from the
// confidential store.
"could not unpack merged bid ids",
"precompile buildEthBlock (0000000000000000000000000000000042100001) not allowed on 00000000000000000000000000000000",
"no caller of confidentialStoreStore (0000000000000000000000000000000042020000) is allowed on 00000000000000000000000000000000",
"no caller of confidentialStoreRetrieve (0000000000000000000000000000000042020001) is allowed on 00000000000000000000000000000000",
}

for name, addr := range artifacts.SuaveMethods {
Expand Down
73 changes: 61 additions & 12 deletions core/vm/suave.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"time"

"golang.org/x/exp/slices"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/metrics"
Expand Down Expand Up @@ -83,40 +85,87 @@ func (p *SuavePrecompiledContractWrapper) Run(input []byte) ([]byte, error) {
}()
}

var ret []byte
var err error

switch p.addr {
case isConfidentialAddress:
return (&isConfidentialPrecompile{}).RunConfidential(p.suaveContext, input)
ret, err = (&isConfidentialPrecompile{}).RunConfidential(p.suaveContext, input)

case confidentialInputsAddress:
return (&confidentialInputsPrecompile{}).RunConfidential(p.suaveContext, input)
ret, err = (&confidentialInputsPrecompile{}).RunConfidential(p.suaveContext, input)

case confStoreStoreAddress:
return stub.confidentialStoreStore(input)
ret, err = stub.confidentialStoreStore(input)

case confStoreRetrieveAddress:
return stub.confidentialStoreRetrieve(input)
ret, err = stub.confidentialStoreRetrieve(input)

case newBidAddress:
return stub.newBid(input)
ret, err = stub.newBid(input)

case fetchBidsAddress:
return stub.fetchBids(input)
ret, err = stub.fetchBids(input)

case extractHintAddress:
return stub.extractHint(input)
ret, err = stub.extractHint(input)

case simulateBundleAddress:
return stub.simulateBundle(input)
ret, err = stub.simulateBundle(input)

case buildEthBlockAddress:
return stub.buildEthBlock(input)
ret, err = stub.buildEthBlock(input)

case submitEthBlockBidToRelayAddress:
return stub.submitEthBlockBidToRelay(input)
ret, err = stub.submitEthBlockBidToRelay(input)

case ethcallAddr:
return stub.ethcall(input)
ret, err = stub.ethcall(input)

default:
err = fmt.Errorf("precompile %s not found", p.addr)
}

if err != nil && ret == nil {
ret = []byte(err.Error())
}

return ret, err
}

// Returns the caller
func checkIsPrecompileCallAllowed(suaveContext *SuaveContext, precompile common.Address, bid suave.Bid) (common.Address, error) {
anyPeekerAllowed := slices.Contains(bid.AllowedPeekers, suave.AllowedPeekerAny)
if anyPeekerAllowed {
for i := len(suaveContext.CallerStack) - 1; i >= 0; i-- {
caller := suaveContext.CallerStack[i]
if caller != nil && *caller != precompile {
return *caller, nil
}
}

return precompile, nil
}

// In question!
// For now both the precompile *and* at least one caller must be allowed to allow access to bid data
// Alternative is to simply allow if any of the callers is allowed
isPrecompileAllowed := slices.Contains(bid.AllowedPeekers, precompile)

// Special case for confStore as those are implicitly allowed
if !isPrecompileAllowed && precompile != confStoreStoreAddress && precompile != confStoreRetrieveAddress {
return common.Address{}, fmt.Errorf("precompile %s (%x) not allowed on %x", artifacts.PrecompileAddressToName(precompile), precompile, bid.Id)
}

for i := len(suaveContext.CallerStack) - 1; i >= 0; i-- {
caller := suaveContext.CallerStack[i]
if caller == nil || *caller == precompile {
continue
}
if slices.Contains(bid.AllowedPeekers, *caller) {
return *caller, nil
}
}

return nil, fmt.Errorf("precompile %s not found", p.addr)
return common.Address{}, fmt.Errorf("no caller of %s (%x) is allowed on %x", artifacts.PrecompileAddressToName(precompile), precompile, bid.Id)
}
3 changes: 3 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,9 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
}

_, result, finalize, err := runMEVM(ctx, b, state, header, tx, msg)
if err != nil {
return nil, err
}
if err := finalize(); err != suave.ErrUnsignedFinalize {
return nil, err
}
Expand Down
3 changes: 3 additions & 0 deletions suave/core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/ethereum/go-ethereum/node"
)

var AllowedPeekerAny = common.HexToAddress("0x04994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829") // "*"

type Bytes = hexutil.Bytes
type BidId = types.BidId

Expand Down Expand Up @@ -44,6 +46,7 @@ var ConfStoreAllowedAny common.Address = common.HexToAddress("0x42")

var (
ErrBidAlreadyPresent = errors.New("bid already present")
ErrBidNotFound = errors.New("bid not found")
ErrUnsignedFinalize = errors.New("finalize called with unsigned transaction, refusing to propagate")
)

Expand Down
2 changes: 1 addition & 1 deletion suave/cstore/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func (e *ConfidentialStoreEngine) Retrieve(bidId suave.BidId, caller common.Addr
return []byte{}, fmt.Errorf("confidential engine: could not fetch bid %x while retrieving: %w", bidId, err)
}

if !slices.Contains(bid.AllowedPeekers, caller) {
if !slices.Contains(bid.AllowedPeekers, caller) && !slices.Contains(bid.AllowedPeekers, suave.AllowedPeekerAny) {
return []byte{}, fmt.Errorf("confidential engine: %x not allowed to retrieve %s on %x", caller, key, bidId)
}

Expand Down
2 changes: 1 addition & 1 deletion suave/cstore/transactional_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (s *TransactionalStore) Retrieve(bidId suave.BidId, caller common.Address,
return nil, err
}

if !slices.Contains(bid.AllowedPeekers, caller) {
if !slices.Contains(bid.AllowedPeekers, caller) && !slices.Contains(bid.AllowedPeekers, suave.AllowedPeekerAny) {
return nil, fmt.Errorf("confidential store transaction: %x not allowed to retrieve %s on %x", caller, key, bidId)
}

Expand Down
2 changes: 1 addition & 1 deletion suave/e2e/workflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ func TestBlockBuildingPrecompiles(t *testing.T) {

bid, err := fr.ConfidentialEngine().InitializeBid(types.Bid{
DecryptionCondition: uint64(1),
AllowedPeekers: []common.Address{{0x41, 0x42, 0x43}, buildEthBlockAddress},
AllowedPeekers: []common.Address{suave.AllowedPeekerAny},
AllowedStores: []common.Address{fr.ExecutionNode()},
Version: "default:v0:ethBundles",
}, dummyCreationTx)
Expand Down

0 comments on commit 9e77af3

Please sign in to comment.