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

Collecting two extra timestamps in the block lifecycle #301

Merged
merged 1 commit into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 15 additions & 13 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type IDatabaseService interface {
GetValidatorRegistration(pubkey string) (*ValidatorRegistrationEntry, error)
GetValidatorRegistrationsForPubkeys(pubkeys []string) ([]*ValidatorRegistrationEntry, error)

SaveBuilderBlockSubmission(payload *common.BuilderSubmitBlockRequest, simError error, receivedAt time.Time) (entry *BuilderBlockSubmissionEntry, err error)
SaveBuilderBlockSubmission(payload *common.BuilderSubmitBlockRequest, simError error, receivedAt, eligibleAt time.Time) (entry *BuilderBlockSubmissionEntry, err error)
GetBlockSubmissionEntry(slot uint64, proposerPubkey, blockHash string) (entry *BuilderBlockSubmissionEntry, err error)
GetBuilderSubmissions(filters GetBuilderSubmissionsFilters) ([]*BuilderBlockSubmissionEntry, error)
GetBuilderSubmissionsBySlots(slotFrom, slotTo uint64) (entries []*BuilderBlockSubmissionEntry, err error)
Expand All @@ -33,7 +33,7 @@ type IDatabaseService interface {
GetExecutionPayloads(idFirst, idLast uint64) (entries []*ExecutionPayloadEntry, err error)
DeleteExecutionPayloads(idFirst, idLast uint64) error

SaveDeliveredPayload(bidTrace *common.BidTraceV2, signedBlindedBeaconBlock *common.SignedBlindedBeaconBlock) error
SaveDeliveredPayload(bidTrace *common.BidTraceV2, signedBlindedBeaconBlock *common.SignedBlindedBeaconBlock, signedAt time.Time) error
GetNumDeliveredPayloads() (uint64, error)
GetRecentDeliveredPayloads(filters GetPayloadsFilters) ([]*DeliveredPayloadEntry, error)
GetDeliveredPayloads(idFirst, idLast uint64) (entries []*DeliveredPayloadEntry, err error)
Expand Down Expand Up @@ -89,8 +89,8 @@ func (s *DatabaseService) prepareNamedQueries() (err error) {

// Insert block builder submission
query = `INSERT INTO ` + vars.TableBuilderBlockSubmission + `
(received_at, execution_payload_id, sim_success, sim_error, signature, slot, parent_hash, block_hash, builder_pubkey, proposer_pubkey, proposer_fee_recipient, gas_used, gas_limit, num_tx, value, epoch, block_number) VALUES
(:received_at, :execution_payload_id, :sim_success, :sim_error, :signature, :slot, :parent_hash, :block_hash, :builder_pubkey, :proposer_pubkey, :proposer_fee_recipient, :gas_used, :gas_limit, :num_tx, :value, :epoch, :block_number)
(received_at, eligible_at, execution_payload_id, sim_success, sim_error, signature, slot, parent_hash, block_hash, builder_pubkey, proposer_pubkey, proposer_fee_recipient, gas_used, gas_limit, num_tx, value, epoch, block_number) VALUES
(:received_at, :eligible_at, :execution_payload_id, :sim_success, :sim_error, :signature, :slot, :parent_hash, :block_hash, :builder_pubkey, :proposer_pubkey, :proposer_fee_recipient, :gas_used, :gas_limit, :num_tx, :value, :epoch, :block_number)
RETURNING id`
s.nstmtInsertBlockBuilderSubmission, err = s.DB.PrepareNamed(query)
return err
Expand Down Expand Up @@ -165,7 +165,7 @@ func (s *DatabaseService) GetLatestValidatorRegistrations(timestampOnly bool) ([
return registrations, err
}

func (s *DatabaseService) SaveBuilderBlockSubmission(payload *common.BuilderSubmitBlockRequest, simError error, receivedAt time.Time) (entry *BuilderBlockSubmissionEntry, err error) {
func (s *DatabaseService) SaveBuilderBlockSubmission(payload *common.BuilderSubmitBlockRequest, simError error, receivedAt, eligibleAt time.Time) (entry *BuilderBlockSubmissionEntry, err error) {
// Save execution_payload: insert, or if already exists update to be able to return the id ('on conflict do nothing' doesn't return an id)
execPayloadEntry, err := PayloadToExecPayloadEntry(payload)
if err != nil {
Expand All @@ -185,6 +185,7 @@ func (s *DatabaseService) SaveBuilderBlockSubmission(payload *common.BuilderSubm

blockSubmissionEntry := &BuilderBlockSubmissionEntry{
ReceivedAt: NewNullTime(receivedAt),
EligibleAt: NewNullTime(eligibleAt),
ExecutionPayloadID: NewNullInt64(execPayloadEntry.ID),

SimSuccess: simError == nil,
Expand Down Expand Up @@ -214,7 +215,7 @@ func (s *DatabaseService) SaveBuilderBlockSubmission(payload *common.BuilderSubm
}

func (s *DatabaseService) GetBlockSubmissionEntry(slot uint64, proposerPubkey, blockHash string) (entry *BuilderBlockSubmissionEntry, err error) {
query := `SELECT id, inserted_at, received_at, execution_payload_id, sim_success, sim_error, signature, slot, parent_hash, block_hash, builder_pubkey, proposer_pubkey, proposer_fee_recipient, gas_used, gas_limit, num_tx, value, epoch, block_number
query := `SELECT id, inserted_at, received_at, eligible_at, execution_payload_id, sim_success, sim_error, signature, slot, parent_hash, block_hash, builder_pubkey, proposer_pubkey, proposer_fee_recipient, gas_used, gas_limit, num_tx, value, epoch, block_number
FROM ` + vars.TableBuilderBlockSubmission + `
WHERE slot=$1 AND proposer_pubkey=$2 AND block_hash=$3
ORDER BY builder_pubkey ASC
Expand All @@ -240,13 +241,14 @@ func (s *DatabaseService) GetExecutionPayloadEntryBySlotPkHash(slot uint64, prop
return entry, err
}

func (s *DatabaseService) SaveDeliveredPayload(bidTrace *common.BidTraceV2, signedBlindedBeaconBlock *common.SignedBlindedBeaconBlock) error {
func (s *DatabaseService) SaveDeliveredPayload(bidTrace *common.BidTraceV2, signedBlindedBeaconBlock *common.SignedBlindedBeaconBlock, signedAt time.Time) error {
_signedBlindedBeaconBlock, err := json.Marshal(signedBlindedBeaconBlock)
if err != nil {
return err
}

deliveredPayloadEntry := DeliveredPayloadEntry{
SignedAt: NewNullTime(signedAt),
SignedBlindedBeaconBlock: NewNullString(string(_signedBlindedBeaconBlock)),

Slot: bidTrace.Slot,
Expand All @@ -268,8 +270,8 @@ func (s *DatabaseService) SaveDeliveredPayload(bidTrace *common.BidTraceV2, sign
}

query := `INSERT INTO ` + vars.TableDeliveredPayload + `
(signed_blinded_beacon_block, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, gas_used, gas_limit, num_tx, value) VALUES
(:signed_blinded_beacon_block, :slot, :epoch, :builder_pubkey, :proposer_pubkey, :proposer_fee_recipient, :parent_hash, :block_hash, :block_number, :gas_used, :gas_limit, :num_tx, :value)
(signed_at, signed_blinded_beacon_block, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, gas_used, gas_limit, num_tx, value) VALUES
(:signed_at, :signed_blinded_beacon_block, :slot, :epoch, :builder_pubkey, :proposer_pubkey, :proposer_fee_recipient, :parent_hash, :block_hash, :block_number, :gas_used, :gas_limit, :num_tx, :value)
ON CONFLICT DO NOTHING`
_, err = s.DB.NamedExec(query, deliveredPayloadEntry)
return err
Expand All @@ -286,7 +288,7 @@ func (s *DatabaseService) GetRecentDeliveredPayloads(queryArgs GetPayloadsFilter
"builder_pubkey": queryArgs.BuilderPubkey,
}

fields := "id, inserted_at, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, num_tx, value, gas_used, gas_limit"
fields := "id, inserted_at, signed_at, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, num_tx, value, gas_used, gas_limit"

whereConds := []string{}
if queryArgs.Slot > 0 {
Expand Down Expand Up @@ -340,7 +342,7 @@ func (s *DatabaseService) GetRecentDeliveredPayloads(queryArgs GetPayloadsFilter
}

func (s *DatabaseService) GetDeliveredPayloads(idFirst, idLast uint64) (entries []*DeliveredPayloadEntry, err error) {
query := `SELECT id, inserted_at, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, num_tx, value, gas_used, gas_limit
query := `SELECT id, inserted_at, signed_at, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, num_tx, value, gas_used, gas_limit
FROM ` + vars.TableDeliveredPayload + `
WHERE id >= $1 AND id <= $2
ORDER BY slot ASC`
Expand All @@ -364,7 +366,7 @@ func (s *DatabaseService) GetBuilderSubmissions(filters GetBuilderSubmissionsFil
"builder_pubkey": filters.BuilderPubkey,
}

fields := "id, inserted_at, received_at, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, num_tx, value, gas_used, gas_limit"
fields := "id, inserted_at, received_at, eligible_at, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, num_tx, value, gas_used, gas_limit"
limit := "LIMIT :limit"

whereConds := []string{
Expand Down Expand Up @@ -412,7 +414,7 @@ func (s *DatabaseService) GetBuilderSubmissions(filters GetBuilderSubmissionsFil
}

func (s *DatabaseService) GetBuilderSubmissionsBySlots(slotFrom, slotTo uint64) (entries []*BuilderBlockSubmissionEntry, err error) {
query := `SELECT id, inserted_at, received_at, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, num_tx, value, gas_used, gas_limit
query := `SELECT id, inserted_at, received_at, eligible_at, slot, epoch, builder_pubkey, proposer_pubkey, proposer_fee_recipient, parent_hash, block_hash, block_number, num_tx, value, gas_used, gas_limit
FROM ` + vars.TableBuilderBlockSubmission + `
WHERE sim_success = true AND slot >= $1 AND slot <= $2
ORDER BY slot ASC, inserted_at ASC`
Expand Down
18 changes: 18 additions & 0 deletions database/migrations/003_bid_add_eligibleat_payload_add_signedat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package migrations

import (
"github.com/flashbots/mev-boost-relay/database/vars"
migrate "github.com/rubenv/sql-migrate"
)

var Migration003AddEligibleAtSignedAt = &migrate.Migration{
Id: "003-add-eligibleat-add-signedat",
Up: []string{`
ALTER TABLE ` + vars.TableBuilderBlockSubmission + ` ADD eligible_at timestamp;
ALTER TABLE ` + vars.TableDeliveredPayload + ` ADD signed_at timestamp;
`},
Down: []string{},

DisableTransactionUp: true,
DisableTransactionDown: true,
}
1 change: 1 addition & 0 deletions database/migrations/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ var Migrations = migrate.MemoryMigrationSource{
Migrations: []*migrate.Migration{
Migration001InitDatabase,
Migration002RemoveIsBestAddReceivedAt,
Migration003AddEligibleAtSignedAt,
},
}
4 changes: 2 additions & 2 deletions database/mockdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (db MockDB) GetLatestValidatorRegistrations(timestampOnly bool) ([]*Validat
return nil, nil
}

func (db MockDB) SaveBuilderBlockSubmission(payload *common.BuilderSubmitBlockRequest, simError error, receivedAt time.Time) (entry *BuilderBlockSubmissionEntry, err error) {
func (db MockDB) SaveBuilderBlockSubmission(payload *common.BuilderSubmitBlockRequest, simError error, receivedAt, eligibleAt time.Time) (entry *BuilderBlockSubmissionEntry, err error) {
return nil, nil
}

Expand Down Expand Up @@ -72,7 +72,7 @@ func (db MockDB) GetBuilderSubmissionsBySlots(slotFrom, slotTo uint64) (entries
return nil, nil
}

func (db MockDB) SaveDeliveredPayload(bidTrace *common.BidTraceV2, signedBlindedBeaconBlock *common.SignedBlindedBeaconBlock) error {
func (db MockDB) SaveDeliveredPayload(bidTrace *common.BidTraceV2, signedBlindedBeaconBlock *common.SignedBlindedBeaconBlock, signedAt time.Time) error {
return nil
}

Expand Down
6 changes: 4 additions & 2 deletions database/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ type BuilderBlockSubmissionEntry struct {
ID int64 `db:"id"`
InsertedAt time.Time `db:"inserted_at"`
ReceivedAt sql.NullTime `db:"received_at"`
EligibleAt sql.NullTime `db:"eligible_at"`

// Delivered ExecutionPayload
ExecutionPayloadID sql.NullInt64 `db:"execution_payload_id"`
Expand Down Expand Up @@ -158,8 +159,9 @@ type BuilderBlockSubmissionEntry struct {
}

type DeliveredPayloadEntry struct {
ID int64 `db:"id"`
InsertedAt time.Time `db:"inserted_at"`
ID int64 `db:"id"`
InsertedAt time.Time `db:"inserted_at"`
SignedAt sql.NullTime `db:"signed_at"`

SignedBlindedBeaconBlock sql.NullString `db:"signed_blinded_beacon_block"`

Expand Down
11 changes: 9 additions & 2 deletions services/api/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,9 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request)
}
}

// Once the signature is verified, we know the proposer is committed to this bid.
signedAt := time.Now().UTC()

// Get the response - from memory, Redis or DB
// note that mev-boost might send getPayload for bids of other relays, thus this code wouldn't find anything
getPayloadResp, err := api.datastore.GetGetPayloadResponse(payload.Slot(), proposerPubkey.String(), payload.BlockHash())
Expand Down Expand Up @@ -897,7 +900,7 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request)
log.WithError(err).Error("failed to get bidTrace for delivered payload from redis")
}

err = api.db.SaveDeliveredPayload(bidTrace, payload)
err = api.db.SaveDeliveredPayload(bidTrace, payload, signedAt)
if err != nil {
log.WithError(err).WithFields(logrus.Fields{
"bidTrace": bidTrace,
Expand Down Expand Up @@ -1221,10 +1224,11 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque
}

var simErr error
var eligibleAt time.Time

// At end of this function, save builder submission to database (in the background)
defer func() {
submissionEntry, err := api.db.SaveBuilderBlockSubmission(payload, simErr, receivedAt)
submissionEntry, err := api.db.SaveBuilderBlockSubmission(payload, simErr, receivedAt, eligibleAt)
if err != nil {
log.WithError(err).WithField("payload", payload).Error("saving builder block submission to database failed")
return
Expand Down Expand Up @@ -1331,6 +1335,9 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque
return
}

// after top bid is updated, the bid is eligible to win the auction.
eligibleAt = time.Now().UTC()

//
// all done
//
Expand Down