Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: OP Keccak commitment support #59

Merged
merged 8 commits into from
Jul 19, 2024
13 changes: 11 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGSSTRING +=-X main.Version=$(VERSION)
LDFLAGS := -ldflags "$(LDFLAGSSTRING)"

E2ETEST = INTEGRATION=true go test -timeout 1m -v ./e2e -parallel 4 -deploy-config ../.devnet/devnetL1.json

.PHONY: eigenda-proxy
eigenda-proxy:
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/eigenda-proxy ./cmd/server
Expand All @@ -20,6 +22,12 @@ eigenda-proxy:
docker-build:
@docker build -t $(APP_NAME) .

run-minio:
docker run -p 4566:9000 -d -e "MINIO_ROOT_USER=minioadmin" -e "MINIO_ROOT_PASSWORD=minioadmin" --name minio minio/minio server /data

stop-minio:
docker stop minio && docker rm minio

run-server:
./bin/eigenda-proxy

Expand All @@ -29,8 +37,9 @@ clean:
test:
go test -v ./... -parallel 4

e2e-test:
INTEGRATION=true go test -timeout 1m -v ./e2e -parallel 4 -deploy-config ../.devnet/devnetL1.json
e2e-test: run-minio
$(E2ETEST); \
make stop-minio

holesky-test:
TESTNET=true go test -timeout 50m -v ./e2e -parallel 4 -deploy-config ../.devnet/devnetL1.json
Expand Down
8 changes: 3 additions & 5 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"fmt"
"io"
"net/http"

"github.com/Layr-Labs/eigenda-proxy/server"
)

// TODO: Add support for custom http client option
Expand All @@ -18,7 +16,7 @@ type Config struct {
// ProxyClient is an interface for communicating with the EigenDA proxy server
type ProxyClient interface {
Health() error
GetData(ctx context.Context, cert []byte, domain server.DomainType) ([]byte, error)
GetData(ctx context.Context, cert []byte) ([]byte, error)
SetData(ctx context.Context, b []byte) ([]byte, error)
}

Expand Down Expand Up @@ -59,8 +57,8 @@ func (c *client) Health() error {
}

// GetData fetches blob data associated with a DA certificate
func (c *client) GetData(ctx context.Context, comm []byte, domain server.DomainType) ([]byte, error) {
url := fmt.Sprintf("%s/get/0x%x?domain=%s&commitment_mode=simple", c.cfg.URL, comm, domain.String())
func (c *client) GetData(ctx context.Context, comm []byte) ([]byte, error) {
url := fmt.Sprintf("%s/get/0x%x?commitment_mode=simple", c.cfg.URL, comm)

req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cmd/server/entrypoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ func StartProxySvr(cliCtx *cli.Context) error {

log.Info("Initializing EigenDA proxy server...")

da, err := server.LoadStore(cfg, ctx, log)
daRouter, err := server.LoadStoreRouter(cfg, ctx, log)
if err != nil {
return fmt.Errorf("failed to create store: %w", err)
}
server := server.NewServer(cliCtx.String(server.ListenAddrFlagName), cliCtx.Int(server.PortFlagName), da, log, m)
server := server.NewServer(cliCtx.String(server.ListenAddrFlagName), cliCtx.Int(server.PortFlagName), daRouter, log, m)

if err := server.Start(); err != nil {
return fmt.Errorf("failed to start the DA server")
Expand Down
72 changes: 24 additions & 48 deletions commitments/da_service_op.go
Original file line number Diff line number Diff line change
@@ -1,67 +1,43 @@
package commitments

import (
"fmt"
"log"
)
import "github.com/ethereum/go-ethereum/crypto"

type DAServiceOPCommitmentType byte

const (
EigenDAByte DAServiceOPCommitmentType = 0
EigenDACommitmentType DAServiceOPCommitmentType = 0
)

// DAServiceOPCommitment represents a value of one of two possible types (Keccak256Commitment or DAServiceCommitment).
type DAServiceOPCommitment struct {
eigendaCommitment *EigenDACommitment
// OPCommitment is the binary representation of a commitment.
type DaSvcCommitment interface {
CommitmentType() DAServiceOPCommitmentType
Encode() []byte
Verify(input []byte) error
}

var _ Commitment = (*DAServiceOPCommitment)(nil)
type EigenDASvcCommitment []byte

func OptimismEigenDACommitment(value EigenDACommitment) DAServiceOPCommitment {
return DAServiceOPCommitment{eigendaCommitment: &value}
}

func (e DAServiceOPCommitment) IsEigenDA() bool {
return e.eigendaCommitment != nil
// NewEigenDASvcCommitment creates a new commitment from the given input.
func NewEigenDASvcCommitment(input []byte) EigenDASvcCommitment {
return EigenDASvcCommitment(crypto.Keccak256(input))
}

func (e DAServiceOPCommitment) MustEigenDAValue() EigenDACommitment {
if e.eigendaCommitment != nil {
return *e.eigendaCommitment
// DecodeEigenDASvcCommitment validates and casts the commitment into a Keccak256Commitment.
func DecodeEigenDASvcCommitment(commitment []byte) (EigenDASvcCommitment, error) {
// guard against empty commitments
if len(commitment) == 0 {
return nil, ErrInvalidCommitment
}
log.Panic("CommitmentEither does not contain a Keccak256Commitment value")
return EigenDACommitment{} // This will never be reached, but is required for compilation.
return commitment, nil
}

func (e DAServiceOPCommitment) Marshal() ([]byte, error) {
if e.IsEigenDA() {
eigenDABytes, err := e.MustEigenDAValue().Marshal()
if err != nil {
return nil, err
}
return append([]byte{byte(EigenDAByte)}, eigenDABytes...), nil
} else {
return nil, fmt.Errorf("DAServiceOPCommitment is neither a keccak256 commitment or a DA service commitment")
}
// CommitmentType returns the commitment type of Keccak256.
func (c EigenDASvcCommitment) CommitmentType() DAServiceOPCommitmentType {
return EigenDACommitmentType
}

func (e *DAServiceOPCommitment) Unmarshal(bz []byte) error {
if len(bz) < 1 {
return fmt.Errorf("OP commitment does not contain generic commitment type prefix byte")
}
head := DAServiceOPCommitmentType(bz[0])
tail := bz[1:]
switch head {
case EigenDAByte:
eigendaCommitment := EigenDACommitment{}
err := eigendaCommitment.Unmarshal(tail)
if err != nil {
return err
}
e.eigendaCommitment = &eigendaCommitment
default:
return fmt.Errorf("unrecognized generic commitment type byte: %x", bz[0])
}
return nil
}
// Encode adds a commitment type prefix self describing the commitment.
func (c EigenDASvcCommitment) Encode() []byte {
return append([]byte{byte(EigenDACommitmentType)}, c...)
}
63 changes: 23 additions & 40 deletions commitments/eigenda.go
Original file line number Diff line number Diff line change
@@ -1,58 +1,41 @@
package commitments

import (
"fmt"
"log"
)

// Define the parent and child types
type CertEncodingVersion byte
type CertEncodingCommitment byte

const (
CertEncodingV0 CertEncodingVersion = 0
CertV0 CertEncodingCommitment = 0
)

type EigenDACommitment struct {
certV0 []byte
// OPCommitment is the binary representation of a commitment.
type CertCommitment interface {
CommitmentType() CertEncodingCommitment
Encode() []byte
Verify(input []byte) error
}

var _ Commitment = (*EigenDACommitment)(nil)
type CertCommitmentV0 []byte

func EigenDACertV0(value []byte) EigenDACommitment {
return EigenDACommitment{certV0: value}
}

func (e EigenDACommitment) IsCertV0() bool {
return e.certV0 != nil
// NewV0CertCommitment creates a new commitment from the given input.
func NewV0CertCommitment(input []byte) CertCommitmentV0 {
return CertCommitmentV0(input)
}

func (e EigenDACommitment) MustCertV0Value() []byte {
if e.certV0 != nil {
return e.certV0
// DecodeCertCommitment validates and casts the commitment into a Keccak256Commitment.
func DecodeCertCommitment(commitment []byte) (CertCommitmentV0, error) {
if len(commitment) == 0 {
return nil, ErrInvalidCommitment
}
log.Panic("CommitmentEither does not contain a Keccak256Commitment value")
return nil // This will never be reached, but is required for compilation.
return commitment, nil
}

func (e EigenDACommitment) Marshal() ([]byte, error) {
if e.IsCertV0() {
return append([]byte{byte(CertEncodingV0)}, e.certV0...), nil
} else {
return nil, fmt.Errorf("EigenDADAServiceOPCommitment is of unknown type")
}
// CommitmentType returns the commitment type of Keccak256.
func (c CertCommitmentV0) CommitmentType() CertEncodingCommitment {
return CertV0
}

func (e *EigenDACommitment) Unmarshal(bz []byte) error {
if len(bz) < 1 {
return fmt.Errorf("OP commitment does not contain eigenda commitment encoding version prefix byte")
}
head := CertEncodingVersion(bz[0])
tail := bz[1:]
switch head {
case CertEncodingV0:
e.certV0 = tail
default:
return fmt.Errorf("unrecognized EigenDA commitment encoding type byte: %x", bz[0])
}
return nil
}
// Encode adds a commitment type prefix self describing the commitment.
func (c CertCommitmentV0) Encode() []byte {
return append([]byte{byte(CertV0)}, c...)
}
6 changes: 0 additions & 6 deletions commitments/interface.go

This file was deleted.

78 changes: 78 additions & 0 deletions commitments/mode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package commitments

import (
"encoding/hex"
"fmt"
)

type CommitmentMode string

const (
OptimismGeneric CommitmentMode = "optimism_keccak256"
OptimismAltDA CommitmentMode = "optimism_generic"
SimpleCommitmentMode CommitmentMode = "simple"
)

func StringToCommitmentMode(s string) (CommitmentMode, error) {
switch s {
case string(OptimismGeneric):
return OptimismGeneric, nil
case string(OptimismAltDA):
return OptimismAltDA, nil
case string(SimpleCommitmentMode):
return SimpleCommitmentMode, nil
default:
return "", fmt.Errorf("unknown commitment mode: %s", s)
}
}

func StringToDecodedCommitment(key string, c CommitmentMode) ([]byte, error) {
if len(key) <= 2 {
return nil, fmt.Errorf("commitment is empty")
}

offset := 0
if key[:2] == "0x" {
offset = 2
}

b, err := hex.DecodeString(key[offset:])
if err != nil {
return nil, err
}

switch c {
case OptimismGeneric: // [op_type, ...]
return b[1:], nil

case OptimismAltDA: // [op_type, da_provider, cert_version, ...]
return b[3:], nil

case SimpleCommitmentMode: // [cert_version, ...]
return b[1:], nil

default:
return nil, fmt.Errorf("unknown commitment type")
}
}

func EncodeCommitment(b []byte, c CommitmentMode) ([]byte, error) {

switch c {
case OptimismGeneric:
return Keccak256Commitment(b).Encode(), nil

case OptimismAltDA:
certCommit := NewV0CertCommitment(b).Encode()
svcCommit := EigenDASvcCommitment(certCommit).Encode()
altDACommit := NewGenericCommitment(svcCommit).Encode()
return altDACommit, nil

case SimpleCommitmentMode:
return NewV0CertCommitment(b).Encode(), nil

}

return nil, fmt.Errorf("unknown commitment mode")
}

Loading