Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Rough Implementation of Pre-Confirmations #4

Merged
merged 29 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9b6e61e
Adds a preconfirmation protocol package - with bid recieve and publish.
ckartik Sep 27, 2023
43ce572
Update naming of internal folder to a more fitting name.
ckartik Sep 27, 2023
eaab5be
Adds commitment construction and propogation to bid handling.
ckartik Sep 27, 2023
fbd4f50
Adds handleCommitment function.
ckartik Sep 27, 2023
dbf74fb
WIP - part 2.
ckartik Sep 28, 2023
b406a27
Adds storage abstraction for commitments.
ckartik Sep 28, 2023
76aa376
Removes redundant seperate protocol for commitments.
ckartik Sep 28, 2023
7a21498
Fixes spacing.
ckartik Sep 28, 2023
e6df471
Fixes go vet issues.
ckartik Sep 28, 2023
ffcbc8a
Removes test file from bid.
ckartik Sep 28, 2023
14bedd8
Fixes linter issues.
ckartik Sep 28, 2023
e713036
resolve err linting.
ckartik Sep 28, 2023
b0c85d1
Adds test and fixes bug with signer.
ckartik Sep 29, 2023
2cb0352
Remove redundant return statements.
ckartik Sep 29, 2023
4cb13a5
Adds refactor of preconfs package.
ckartik Sep 29, 2023
83ca314
Correct useage.
ckartik Sep 29, 2023
f36a349
Merge branch 'main' into ckartik/preconf-protocol-impl
ckartik Sep 29, 2023
024da80
fixes go.mod file.
ckartik Sep 29, 2023
0faa14d
Fixes test call.
ckartik Sep 30, 2023
7f8af3c
Update go version to 1.21.1.
ckartik Sep 30, 2023
6593208
Removes redundant comments.
ckartik Sep 30, 2023
6d6f1f8
Nit cleanup.
ckartik Sep 30, 2023
b4e92b4
Return only pointers.
ckartik Sep 30, 2023
ab9ddaa
Updates all common.address function returns to be pointers.
ckartik Oct 1, 2023
fdedfcc
Returns pointer for bid.
ckartik Oct 1, 2023
12c46a3
Updates tests to be more expansive, and reduces redundant code.
ckartik Oct 2, 2023
87d1f3d
Merge branch 'main' into ckartik/preconf-protocol-impl
ckartik Oct 2, 2023
e3d14f9
adds self peer node to p2ptest init.
ckartik Oct 2, 2023
fb3daf0
remove redundant code.
ckartik Oct 2, 2023
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
vendor
**/.idea
**/.vscode
**/.vscode
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@ require (
require (
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.5.0 // indirect
github.com/btcsuite/btcd v0.22.0-beta // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.10.0 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/ethereum/c-kzg-4844 v0.3.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand Down Expand Up @@ -61,6 +67,7 @@ require (
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
Expand All @@ -86,6 +93,7 @@ require (
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.uber.org/dig v1.17.0 // indirect
Expand All @@ -100,4 +108,5 @@ require (
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
google.golang.org/protobuf v1.31.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)
58 changes: 58 additions & 0 deletions go.sum

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pkg/discovery/discovery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func TestDiscovery(t *testing.T) {
}

svc := p2ptest.New(
&client,
p2ptest.WithConnectFunc(func(addr []byte) (p2p.Peer, error) {
if string(addr) != "test" {
return p2p.Peer{}, errors.New("invalid address")
Expand Down
6 changes: 4 additions & 2 deletions pkg/p2p/testing/p2p.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func pipe(a, b *testStream) {
type Option func(*P2PTest)

type P2PTest struct {
self *p2p.Peer
handlers map[string]p2p.ProtocolSpec
connectFunc func([]byte) (p2p.Peer, error)
addressbookFunc func(p2p.Peer) ([]byte, error)
Expand All @@ -87,9 +88,10 @@ func WithAddressbookFunc(fn func(p p2p.Peer) ([]byte, error)) Option {
}
}

func New(opts ...Option) *P2PTest {
func New(selfNode *p2p.Peer, opts ...Option) *P2PTest {
p := &P2PTest{
handlers: make(map[string]p2p.ProtocolSpec),
self: selfNode,
}

for _, opt := range opts {
Expand Down Expand Up @@ -146,7 +148,7 @@ func (p *P2PTest) NewStream(
go func() {
defer in.Close()

err := handler(context.Background(), peer, in)
err := handler(context.Background(), *p.self, in)
if err != nil {
panic(err)
}
Expand Down
158 changes: 158 additions & 0 deletions pkg/preconfirmation/preconfirmation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package preconfirmation
ckartik marked this conversation as resolved.
Show resolved Hide resolved

import (
"context"
"crypto/ecdsa"
"errors"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/primevprotocol/mev-commit/pkg/p2p"
"github.com/primevprotocol/mev-commit/pkg/p2p/msgpack"
"github.com/primevprotocol/mev-commit/pkg/structures/preconf"
"github.com/primevprotocol/mev-commit/pkg/topology"
)

const (
ProtocolName = "preconfirmation"
ProtocolVersion = "1.0.0"
)

type Preconfirmation struct {
signer preconf.Signer
topo Topology
streamer p2p.Streamer
cs CommitmentsStore
ckartik marked this conversation as resolved.
Show resolved Hide resolved
us UserStore
}

type Topology interface {
GetPeers(topology.Query) []p2p.Peer
}

func New(topo Topology, streamer p2p.Streamer, key *ecdsa.PrivateKey, us UserStore, cs CommitmentsStore) *Preconfirmation {
return &Preconfirmation{
topo: topo,
streamer: streamer,
signer: preconf.PrivateKeySigner{PrivKey: key},
us: us,
cs: cs,
}
}

func (p *Preconfirmation) Protocol() p2p.ProtocolSpec {
return p2p.ProtocolSpec{
Name: ProtocolName,
Version: ProtocolVersion,
StreamSpecs: []p2p.StreamSpec{
{
Name: "bid",
Handler: p.handleBid,
},
},
}
}

// BidHash -> map of preconfs
// Key: BidHash
// Value: List of preconfs
// var commitments map[string][]preconf.PreconfCommitment
type CommitmentsStore interface {
GetCommitments(bidHash []byte) ([]preconf.PreconfCommitment, error)
AddCommitment(bidHash []byte, commitment *preconf.PreconfCommitment) error
}

type UserStore interface {
CheckUserRegistred(*common.Address) bool
}

// SendBid is meant to be called by the searcher to construct and send bids to the builder.
// It takes the txnHash, the bid amount in wei and the maximum valid block number.
// It waits for commitments from all builders and then returns.
// TODO(@ckartik): construct seperate go-routine to wait for commitments, with a context that cancels if a timeout is reached.
//
// It returns an error if the bid is not valid.
func (p *Preconfirmation) SendBid(ctx context.Context, txnHash string, bidamt *big.Int, blockNumber *big.Int) error {
ckartik marked this conversation as resolved.
Show resolved Hide resolved
signedBid, err := preconf.ConstructSignedBid(bidamt, txnHash, blockNumber, p.signer)
if err != nil {
return err
}

builders := p.topo.GetPeers(topology.Query{Type: p2p.PeerTypeBuilder})

// TODO(@ckartik): Push into a channel and process in parallel
for _, builder := range builders {
// Create a new connection
builderStream, err := p.streamer.NewStream(ctx, builder, ProtocolName, ProtocolVersion, "bid")
if err != nil {
return err
}

r, w := msgpack.NewReaderWriter[preconf.PreconfCommitment, preconf.PreConfBid](builderStream)
err = w.WriteMsg(ctx, signedBid)
if err != nil {
return err
}

commitment, err := r.ReadMsg(ctx)
if err != nil {
return err
}

// Process commitment as a searcher
_, err = commitment.VerifyBuilderSignature()
if err != nil {
return err
}
_, err = commitment.VerifySearcherSignature()
if err != nil {
return err
}

// Verify the bid details correspond.
err = p.cs.AddCommitment(signedBid.BidHash, commitment)
if err != nil {
return err
}
}

return nil
}

var ErrInvalidSearcherTypeForBid = errors.New("invalid searcher type for bid")

// handlebid is the function that is called when a bid is received
// It is meant to be used by the builder exclusively to read the bid value from the searcher.
func (p *Preconfirmation) handleBid(
ctx context.Context,
peer p2p.Peer,
stream p2p.Stream,
) error {
if peer.Type != p2p.PeerTypeSearcher {
return ErrInvalidSearcherTypeForBid
}

// TODO(@ckartik): Change to reader only once availble
r, w := msgpack.NewReaderWriter[preconf.PreConfBid, preconf.PreconfCommitment](stream)
bid, err := r.ReadMsg(ctx)
if err != nil {
return err
}

ethAddress, err := bid.VerifySearcherSignature()
if err != nil {
return err
}

if p.us.CheckUserRegistred(ethAddress) {
// More conditional Logic to determine signing of bid
commitment, err := preconf.ConstructCommitment(*bid, p.signer)
if err != nil {
return err
}

return w.WriteMsg(ctx, commitment)
}

return nil
}
93 changes: 93 additions & 0 deletions pkg/preconfirmation/preconfirmation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package preconfirmation_test

import (
"context"
"math/big"
"sync"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/primevprotocol/mev-commit/pkg/p2p"
p2ptest "github.com/primevprotocol/mev-commit/pkg/p2p/testing"
"github.com/primevprotocol/mev-commit/pkg/preconfirmation"
"github.com/primevprotocol/mev-commit/pkg/structures/preconf"
"github.com/primevprotocol/mev-commit/pkg/topology"
)

type testTopo struct {
mu sync.Mutex
peers []p2p.Peer
}

func (t *testTopo) AddPeers(peers ...p2p.Peer) {
t.mu.Lock()
defer t.mu.Unlock()

t.peers = append(t.peers, peers...)
}

func (t *testTopo) GetPeers(q topology.Query) []p2p.Peer {
t.mu.Lock()
defer t.mu.Unlock()

return []p2p.Peer{{EthAddress: common.HexToAddress("0x2"), Type: p2p.PeerTypeBuilder}}
}

func (t *testTopo) Connected(p2p.Peer) {
}

func (t *testTopo) Disconnected(p2p.Peer) {
}

type testCommitmentStore struct {
}

func (t *testCommitmentStore) GetCommitments(bidHash []byte) ([]preconf.PreconfCommitment, error) {
return []preconf.PreconfCommitment{}, nil
}

func (t *testCommitmentStore) AddCommitment(bidHash []byte, commitment *preconf.PreconfCommitment) error {
return nil
}

type testUserStore struct {
}

func (t *testUserStore) CheckUserRegistred(_ *common.Address) bool {
return true
}

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

t.Run("ok", func(t *testing.T) {
client := p2p.Peer{
EthAddress: common.HexToAddress("0x1"),
Type: p2p.PeerTypeSearcher,
}
server := p2p.Peer{
EthAddress: common.HexToAddress("0x2"),
Type: p2p.PeerTypeBuilder,
}

svc := p2ptest.New(
&client,
)

topo := &testTopo{}
us := &testUserStore{}
cs := &testCommitmentStore{}
key, _ := crypto.GenerateKey()
p := preconfirmation.New(topo, svc, key, us, cs)

// svc.SetPeerHandler(client, p.Protocol())
svc.SetPeerHandler(server, p.Protocol())

err := p.SendBid(context.Background(), "0x4c03a845396b770ad41b975d6bd3bf8c2bd5cca36867a3301f9598f2e3e9518d", big.NewInt(10), big.NewInt(10))
ckartik marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
t.Fatal(err)
}

})
}
Loading