Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b665a4b
update config to support Hoodi testnet instead of Holesky
blockchainluffy Aug 27, 2025
066d739
Merge pull request #1 from blockchainluffy/hoodi-testnet-version
blockchainluffy Aug 27, 2025
206b648
Merge branch 'main' into main
blockchainluffy Aug 27, 2025
6240079
Merge branch 'primev:main' into main
blockchainluffy Sep 3, 2025
5fe5f5b
add new bidOption for shutterised bids
blockchainluffy Sep 4, 2025
d79f19e
update bidOptions to include explicit shutterised bidOption
blockchainluffy Sep 4, 2025
58ef898
update shutterised bid option handling for bidder node rpc
blockchainluffy Sep 5, 2025
bc30c45
add encrypted_tx as separate field in shutterised bid option
blockchainluffy Sep 22, 2025
0ea516c
Update p2p/gen/openapi/debugapi/v1/debugapi.swagger.yaml
blockchainluffy Sep 23, 2025
5c2a1c4
Update p2p/gen/openapi/providerapi/v1/providerapi.swagger.yaml
blockchainluffy Sep 23, 2025
f5d5d5f
Update p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml
blockchainluffy Sep 23, 2025
707b371
Update p2p/gen/openapi/providerapi/v1/providerapi.swagger.yaml
blockchainluffy Sep 23, 2025
f3b2e69
Update p2p/rpc/bidderapi/v1/bidderapi.proto
blockchainluffy Sep 23, 2025
8b21eef
Update p2p/rpc/providerapi/v1/providerapi.proto
blockchainluffy Sep 23, 2025
389927a
Update p2p/rpc/providerapi/v1/providerapi.proto
blockchainluffy Sep 23, 2025
5384784
update provider api to include encrypted_tx field for shutterised bid…
blockchainluffy Sep 23, 2025
8862668
update provider bid processing to use tagless switch
blockchainluffy Sep 23, 2025
25bcb67
update shutterised bid option validations
blockchainluffy Sep 24, 2025
a34f4ea
Merge pull request #5 from blockchainluffy/shutter-bid-opts-impl
blockchainluffy Oct 14, 2025
ece9e4f
Merge branch 'main' into main
blockchainluffy Oct 14, 2025
404e967
fix: accept identity prefix with 0x prefix
blockchainluffy Oct 14, 2025
1d4f6c5
fix: use protobuf validation for shutterised bid option
blockchainluffy Oct 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,488 changes: 809 additions & 679 deletions p2p/gen/go/bidderapi/v1/bidderapi.pb.go

Large diffs are not rendered by default.

1,255 changes: 692 additions & 563 deletions p2p/gen/go/providerapi/v1/providerapi.pb.go

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ definitions:
positionConstraint:
$ref: '#/definitions/bidderapiv1PositionConstraint'
description: Position constraint for the transaction in the block.
shutterisedBidOption:
$ref: '#/definitions/bidderapiv1ShutterisedBidOption'
description: Shutterised bid option for the transaction in the block.
bidderapiv1BidOptions:
type: object
properties:
Expand Down Expand Up @@ -556,6 +559,17 @@ definitions:
- BASIS_PERCENTILE: Position is a percentile of the block size
- BASIS_ABSOLUTE: Position is an absolute position in the block
- BASIS_GAS_PERCENTILE: Position is a percentile of the gas used in the block
bidderapiv1ShutterisedBidOption:
type: object
properties:
identityPrefix:
type: string
description: Hex string encoding of the identity prefix of the transaction that the bidder wants to include in the block.
pattern: '[a-fA-F0-9]{64}'
encryptedTx:
type: string
description: Hex string encoding of the encrypted transaction that the bidder wants to include in the block.
pattern: '[a-fA-F0-9]+'
googlerpcStatus:
type: object
properties:
Expand Down
2 changes: 1 addition & 1 deletion p2p/gen/openapi/debugapi/v1/debugapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ definitions:
`NullValue` is a singleton enumeration to represent the null value for the
`Value` type union.

The JSON representation for `NullValue` is JSON `null`.
The JSON representation for `NullValue` is JSON `null`.
v1CancelTransactionResponse:
type: object
example:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ definitions:
`NullValue` is a singleton enumeration to represent the null value for the
`Value` type union.

The JSON representation for `NullValue` is JSON `null`.
The JSON representation for `NullValue` is JSON `null`.
v1Notification:
type: object
properties:
Expand Down
14 changes: 14 additions & 0 deletions p2p/gen/openapi/providerapi/v1/providerapi.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ definitions:
positionConstraint:
$ref: '#/definitions/providerapiv1PositionConstraint'
description: Position constraint for the transaction in the block.
shutterisedBidOption:
$ref: '#/definitions/providerapiv1ShutterisedBidOption'
description: Shutterised bid option for the transaction in the block.
providerapiv1BidOptions:
type: object
properties:
Expand Down Expand Up @@ -369,6 +372,17 @@ definitions:
- BASIS_PERCENTILE: Position is a percentile of the block size
- BASIS_ABSOLUTE: Position is an absolute position in the block
- BASIS_GAS_PERCENTILE: Position is a percentile of the gas used in the block
providerapiv1ShutterisedBidOption:
type: object
properties:
identityPrefix:
type: string
description: Hex string encoding of the identity prefix of the transaction that the bidder wants to include in the block.
pattern: '[a-fA-F0-9]{64}'
encryptedTx:
type: string
description: Hex string encoding of the encrypted transaction that the bidder wants to include in the block.
pattern: '[a-fA-F0-9]{64}'
v1BidResponse:
type: object
example:
Expand Down
1 change: 1 addition & 0 deletions p2p/pkg/rpc/bidder/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func (s *Service) SendBid(
case len(bid.RawTransactions) > 0:
strBuilder := new(strings.Builder)
for i, rawTx := range bid.RawTransactions {

rawTxnBytes, err := hex.DecodeString(strings.TrimPrefix(rawTx, "0x"))
if err != nil {
s.logger.Error("decoding raw transaction", "error", err)
Expand Down
216 changes: 216 additions & 0 deletions p2p/pkg/rpc/bidder/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,222 @@ func TestGetBidInfo(t *testing.T) {
})
}

func TestShutterisedBidOptions(t *testing.T) {
t.Parallel()

client := startServer(t)

t.Run("shutterised bid option validation", func(t *testing.T) {
type testCase struct {
name string
identityPrefix string
encryptedTx string
expectError bool
}

for _, tc := range []testCase{
{
name: "valid shutterised bid option",
identityPrefix: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
encryptedTx: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
expectError: false,
},
{
name: "invalid identity prefix - too short",
identityPrefix: "0x1234567890abcdef",
encryptedTx: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
expectError: true,
},
{
name: "invalid identity prefix - contains non-hex",
identityPrefix: "0xgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg",
encryptedTx: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
expectError: true,
},
{
name: "empty identity prefix",
identityPrefix: "",
encryptedTx: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
expectError: true,
},
{
name: "invalid encrypted tx - contains non-hex",
identityPrefix: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
encryptedTx: "0xgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg",
expectError: true,
},
{
name: "empty encrypted tx",
identityPrefix: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
encryptedTx: "",
expectError: true,
},
{
name: "both fields empty",
identityPrefix: "",
encryptedTx: "",
expectError: true,
},
} {
t.Run(tc.name, func(t *testing.T) {
rcv, err := client.SendBid(context.Background(), &bidderapiv1.Bid{
TxHashes: []string{"abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"},
Amount: "1000000000000000000",
BlockNumber: 1,
DecayStartTimestamp: 10,
DecayEndTimestamp: 20,
BidOptions: &bidderapiv1.BidOptions{
Options: []*bidderapiv1.BidOption{
{
Opt: &bidderapiv1.BidOption_ShutterisedBidOption{
ShutterisedBidOption: &bidderapiv1.ShutterisedBidOption{
IdentityPrefix: tc.identityPrefix,
EncryptedTx: tc.encryptedTx,
},
},
},
},
},
})

if tc.expectError {
// For invalid cases, we expect validation error during SendBid
if err != nil {
// Check that it's a validation error
if !strings.Contains(err.Error(), "validation") {
t.Fatalf("expected validation error, got: %v", err)
}
return
}

// If no error during SendBid, check if error comes during Recv()
_, err = rcv.Recv()
if err == nil {
t.Fatalf("expected validation error but got none")
}
if !strings.Contains(err.Error(), "validation") {
t.Fatalf("expected validation error during recv, got: %v", err)
}
return
}

// For valid cases, we expect no error during SendBid
if err != nil {
t.Fatalf("unexpected error for valid shutterised bid option: %v", err)
}

// Verify we get preconfs
count := 0
for {
_, err := rcv.Recv()
if err != nil {
if errors.Is(err, io.EOF) {
break
}
t.Fatalf("error receiving preconfs: %v", err)
}
count++
}
if count != 2 {
t.Fatalf("expected 2 preconfs, got %v", count)
}
})
}
})

t.Run("multiple shutterised bid options", func(t *testing.T) {
rcv, err := client.SendBid(context.Background(), &bidderapiv1.Bid{
TxHashes: []string{
common.HexToHash("0x0000ab").Hex()[2:],
common.HexToHash("0x0000cd").Hex()[2:],
},
Amount: "1000000000000000000",
BlockNumber: 1,
DecayStartTimestamp: 10,
DecayEndTimestamp: 20,
BidOptions: &bidderapiv1.BidOptions{
Options: []*bidderapiv1.BidOption{
{
Opt: &bidderapiv1.BidOption_ShutterisedBidOption{
ShutterisedBidOption: &bidderapiv1.ShutterisedBidOption{
IdentityPrefix: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
EncryptedTx: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
},
},
},
{
Opt: &bidderapiv1.BidOption_ShutterisedBidOption{
ShutterisedBidOption: &bidderapiv1.ShutterisedBidOption{
IdentityPrefix: "fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321",
EncryptedTx: "0987654321fedcba0987654321fedcba0987654321fedcba0987654321fedcba",
},
},
},
},
},
})
if err != nil {
t.Fatalf("error sending bid with multiple shutterised options: %v", err)
}

count := 0
for {
_, err := rcv.Recv()
if err != nil {
if errors.Is(err, io.EOF) {
break
}
t.Fatalf("error receiving preconfs: %v", err)
}
count++
}
if count != 2 {
t.Fatalf("expected 2 preconfs, got %v", count)
}
})

t.Run("mixed bid options with one invalid shutterised option", func(t *testing.T) {
rcv, err := client.SendBid(context.Background(), &bidderapiv1.Bid{
TxHashes: []string{
common.HexToHash("0x0000ab").Hex()[2:],
common.HexToHash("0x0000cd").Hex()[2:],
},
Amount: "1000000000000000000",
BlockNumber: 1,
DecayStartTimestamp: 10,
DecayEndTimestamp: 20,
BidOptions: &bidderapiv1.BidOptions{
Options: []*bidderapiv1.BidOption{
{
Opt: &bidderapiv1.BidOption_ShutterisedBidOption{
ShutterisedBidOption: &bidderapiv1.ShutterisedBidOption{
IdentityPrefix: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
EncryptedTx: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
},
},
},
{
Opt: &bidderapiv1.BidOption_ShutterisedBidOption{
ShutterisedBidOption: &bidderapiv1.ShutterisedBidOption{
IdentityPrefix: "",
EncryptedTx: "0x0987654321fedcba0987654321fedcba0987654321fedcba0987654321fedcba",
},
},
},
},
},
})
if err != nil {
t.Fatalf("error sending bid: %v", err)
}

_, err = rcv.Recv()
if err == nil || !strings.Contains(err.Error(), "bid_options.options[1].shutterised_bid_option.identity_prefix: identity_prefix must be a valid 32 bytes hex string. [identity_prefix]") {
t.Fatalf("expected error about invalid shutterised option, got %v", err)
}
})
}

type dmTestSub struct{ ch chan error }

func (s *dmTestSub) Unsubscribe() {}
Expand Down
11 changes: 11 additions & 0 deletions p2p/pkg/rpc/provider/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ func (s *Service) ProcessBid(
},
}
opts.Options = append(opts.Options, opt)
case bOpt.GetShutterisedBidOption() != nil:
c := bOpt.GetShutterisedBidOption()
opt := &providerapiv1.BidOption{
Opt: &providerapiv1.BidOption_ShutterisedBidOption{
ShutterisedBidOption: &providerapiv1.ShutterisedBidOption{
IdentityPrefix: c.GetIdentityPrefix(),
EncryptedTx: c.GetEncryptedTx(),
},
},
}
opts.Options = append(opts.Options, opt)
}
}
}
Expand Down
Loading
Loading