-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #52 from chainbound/feat/bolt-boost-constraints
feat(mev-boost): updated constraints API
- Loading branch information
Showing
8 changed files
with
158 additions
and
166 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,146 +1,96 @@ | ||
package server | ||
|
||
import ( | ||
"encoding/hex" | ||
"encoding/json" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/attestantio/go-eth2-client/spec/phase0" | ||
"github.com/pkg/errors" | ||
"github.com/chainbound/shardmap" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
) | ||
|
||
type SignedConstraintSubmission struct { | ||
Message *ConstraintSubmission | ||
Signature phase0.BLSSignature `ssz-size:"96"` | ||
} | ||
type BatchedSignedConstraints = []*SignedConstraints | ||
|
||
type signedConstraintSubmissionJSON struct { | ||
Message *ConstraintSubmission `json:"message"` | ||
Signature string `json:"signature"` | ||
type SignedConstraints struct { | ||
Message ConstraintsMessage `json:"message"` | ||
Signature HexBytes `json:"signature"` | ||
} | ||
|
||
func (s *SignedConstraintSubmission) MarshalJSON() ([]byte, error) { | ||
return json.Marshal(&signedConstraintSubmissionJSON{ | ||
Message: s.Message, | ||
Signature: fmt.Sprintf("%#x", s.Signature), | ||
}) | ||
type ConstraintsMessage struct { | ||
ValidatorIndex uint64 | ||
Slot uint64 | ||
Constraints []*Constraint | ||
} | ||
|
||
func (s *SignedConstraintSubmission) UnmarshalJSON(input []byte) error { | ||
var data signedConstraintSubmissionJSON | ||
if err := json.Unmarshal(input, &data); err != nil { | ||
return errors.Wrap(err, "invalid JSON") | ||
} | ||
|
||
if data.Message == nil { | ||
return errors.New("message missing") | ||
} | ||
|
||
s.Message = data.Message | ||
|
||
if data.Signature == "" { | ||
return errors.New("signature missing") | ||
} | ||
|
||
signature, err := hex.DecodeString(strings.TrimPrefix(data.Signature, "0x")) | ||
if err != nil { | ||
return errors.Wrap(err, "invalid signature") | ||
} | ||
|
||
if len(signature) != phase0.SignatureLength { | ||
return errors.New("incorrect length for signature") | ||
} | ||
copy(s.Signature[:], signature) | ||
|
||
return nil | ||
} | ||
|
||
type ConstraintSubmission struct { | ||
Slot uint64 | ||
TxHash phase0.Hash32 `ssz-size:"32"` | ||
RawTx Transaction `ssz-max:"1073741824"` | ||
type Constraint struct { | ||
Tx Transaction | ||
Index *uint64 | ||
} | ||
|
||
type constraintSubmissionJSON struct { | ||
Slot uint64 `json:"slot"` | ||
TxHash string `json:"txHash"` | ||
RawTx string `json:"rawTx"` | ||
// ConstraintCache is a cache for constraints. | ||
type ConstraintCache struct { | ||
// map of slots to all constraints for that slot | ||
constraints shardmap.FIFOMap[uint64, map[common.Hash]*Constraint] | ||
} | ||
|
||
func (c *ConstraintSubmission) MarshalJSON() ([]byte, error) { | ||
return json.Marshal(&constraintSubmissionJSON{ | ||
Slot: c.Slot, | ||
TxHash: c.TxHash.String(), | ||
RawTx: fmt.Sprintf("%#x", c.RawTx), | ||
}) | ||
// NewConstraintCache creates a new constraint cache. | ||
// cap is the maximum number of slots to store constraints for. | ||
func NewConstraintCache(cap int) *ConstraintCache { | ||
return &ConstraintCache{ | ||
constraints: *shardmap.NewFIFOMap[uint64, map[common.Hash]*Constraint](int(cap), 1, shardmap.HashUint64), | ||
} | ||
} | ||
|
||
func (c *ConstraintSubmission) UnmarshalJSON(input []byte) error { | ||
var data constraintSubmissionJSON | ||
if err := json.Unmarshal(input, &data); err != nil { | ||
return err | ||
// AddInclusionConstraint adds an inclusion constraint to the cache at the given slot for the given transaction. | ||
func (c *ConstraintCache) AddInclusionConstraint(slot uint64, tx Transaction, index *uint64) error { | ||
if _, exists := c.constraints.Get(slot); !exists { | ||
c.constraints.Put(slot, make(map[common.Hash]*Constraint)) | ||
} | ||
|
||
c.Slot = data.Slot | ||
|
||
txHash, err := hex.DecodeString((strings.TrimPrefix(data.TxHash, "0x"))) | ||
// parse transaction to get its hash and store it in the cache | ||
// for constant time lookup later | ||
var parsedTx = new(types.Transaction) | ||
err := parsedTx.UnmarshalBinary(tx) | ||
if err != nil { | ||
return errors.Wrap(err, "invalid tx hash") | ||
return err | ||
} | ||
|
||
copy(c.TxHash[:], txHash) | ||
|
||
rawTx, err := hex.DecodeString((strings.TrimPrefix(data.RawTx, "0x"))) | ||
if err != nil { | ||
return errors.Wrap(err, "invalid raw tx") | ||
m, _ := c.constraints.Get(slot) | ||
m[parsedTx.Hash()] = &Constraint{ | ||
Tx: tx, | ||
Index: index, | ||
} | ||
|
||
c.RawTx = rawTx | ||
|
||
return nil | ||
} | ||
|
||
// Constraints is a map of constraints for a block. | ||
type Constraints = map[phase0.Hash32]*Constraint | ||
|
||
// Constraint is a constraint on a block. For now just preconfirmations | ||
// or inclusion constraints. | ||
type Constraint struct { | ||
RawTx Transaction `json:"rawTx"` | ||
} | ||
|
||
// ConstraintCache is a cache for constraints. | ||
type ConstraintCache struct { | ||
// map of slots to constraints | ||
constraints map[uint64]Constraints | ||
} | ||
|
||
// NewConstraintCache creates a new constraint cache. | ||
func NewConstraintCache() *ConstraintCache { | ||
return &ConstraintCache{ | ||
// TODO: there should be a maximum length here that we can pre-allocate (probably the lookahead window size) | ||
constraints: make(map[uint64]Constraints), | ||
// AddInclusionConstraints adds multiple inclusion constraints to the cache at the given slot | ||
func (c *ConstraintCache) AddInclusionConstraints(slot uint64, constraints []*Constraint) error { | ||
if _, exists := c.constraints.Get(slot); !exists { | ||
c.constraints.Put(slot, make(map[common.Hash]*Constraint)) | ||
} | ||
} | ||
|
||
// AddInclusionConstraint adds an inclusion constraint to the cache at the given slot for the given transaction. | ||
func (c *ConstraintCache) AddInclusionConstraint(slot uint64, txHash phase0.Hash32, rawTx Transaction) { | ||
if _, exists := c.constraints[slot]; !exists { | ||
c.constraints[slot] = make(map[phase0.Hash32]*Constraint) | ||
m, _ := c.constraints.Get(slot) | ||
for _, constraint := range constraints { | ||
var parsedTx = new(types.Transaction) | ||
err := parsedTx.UnmarshalBinary(constraint.Tx) | ||
if err != nil { | ||
return err | ||
} | ||
m[parsedTx.Hash()] = constraint | ||
} | ||
|
||
c.constraints[slot][txHash] = &Constraint{ | ||
RawTx: rawTx, | ||
} | ||
return nil | ||
} | ||
|
||
// Get gets the constraints at the given slot. | ||
func (c *ConstraintCache) Get(slot uint64) Constraints { | ||
return c.constraints[slot] | ||
func (c *ConstraintCache) Get(slot uint64) (map[common.Hash]*Constraint, bool) { | ||
return c.constraints.Get(slot) | ||
} | ||
|
||
// Delete deletes the constraints at the given slot. | ||
func (c *ConstraintCache) Delete(slot uint64) { | ||
delete(c.constraints, slot) | ||
// FindTransactionByHash finds the constraint for the given transaction hash and returns it. | ||
func (c *ConstraintCache) FindTransactionByHash(txHash common.Hash) (*Constraint, bool) { | ||
for kv := range c.constraints.Iter() { | ||
if constraint, exists := kv.Value[txHash]; exists { | ||
return constraint, true | ||
} | ||
} | ||
return nil, false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.