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

fix: return signed delegations #6

Merged
merged 3 commits into from
Oct 2, 2024
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
24 changes: 8 additions & 16 deletions crates/api/src/builder/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use helix_common::{
}, chain_info::ChainInfo, proofs::{self, verify_multiproofs, ConstraintsWithProofData, InclusionProofs, SignedConstraints, SignedConstraintsWithProofData}, signing::RelaySigningContext, simulator::BlockSimError, versioned_payload::PayloadAndBlobs, BuilderInfo, GossipedHeaderTrace, GossipedPayloadTrace, HeaderSubmissionTrace, SignedBuilderBid, SubmissionTrace
};
use helix_database::{error::DatabaseError, DatabaseService};
use helix_datastore::{types::SaveBidAndUpdateTopBidResponse, Auctioneer};
use helix_datastore::{error::AuctioneerError, types::SaveBidAndUpdateTopBidResponse, Auctioneer};
use helix_housekeeper::{ChainUpdate, PayloadAttributesUpdate, SlotUpdate};
use helix_utils::{get_payload_attributes_key, has_reached_fork, try_decode_into};
use serde::{de, Deserialize};
Expand Down Expand Up @@ -159,7 +159,7 @@ where

/// This endpoint returns a list of signed constraints for a given `slot`.
///
/// Implements this API: <https://chainbound.github.io/bolt-docs/api/relay#constraints>
/// Implements this API: <https://docs.boltprotocol.xyz/api/relay#constraints>
pub async fn constraints(
Extension(api): Extension<Arc<BuilderApi<A, DB, S, G>>>,
Query(slot): Query<SlotQuery>,
Expand Down Expand Up @@ -193,7 +193,7 @@ where

/// This endpoint returns a stream of signed constraints for a given `slot`.
///
/// Implements this API: <https://chainbound.github.io/bolt-docs/api/relay#constraints-stream>
/// Implements this API: <https://docs.boltprotocol.xyz/api/relay#constraints-stream>
pub async fn constraints_stream(
Extension(api): Extension<Arc<BuilderApi<A, DB, S, G>>>,
) -> Sse<impl Stream<Item = Result<Event, BuilderApiError>>> {
Expand Down Expand Up @@ -223,7 +223,7 @@ where
/// This endpoint returns the active delegations for the validator scheduled to propose
/// at the provided `slot`. The delegations are returned as a list of BLS pubkeys.
///
/// Implements this API: <https://chainbound.github.io/bolt-docs/api/relay#delegations>
/// Implements this API: <https://docs.boltprotocol.xyz/api/relay#delegations>
pub async fn delegations(
Extension(api): Extension<Arc<BuilderApi<A, DB, S, G>>>,
Query(slot): Query<SlotQuery>,
Expand All @@ -243,20 +243,12 @@ where

let pubkey = duty.entry.message.public_key.clone();

match api.db.get_validator_delegations(pubkey).await {
match api.auctioneer.get_validator_delegations(pubkey).await {
Ok(delegations) => Ok(Json(delegations)),

Err(err) => {
match err {
DatabaseError::ValidatorDelegationNotFound => {
debug!("No delegations found for validator");
Ok(Json(vec![])) // Return an empty vector if no delegations found
}
_ => {
warn!(error=%err, "Failed to get delegations");
Err(BuilderApiError::DatabaseError(err))
}
}
warn!(error=%err, "Failed to get delegations");
Err(BuilderApiError::AuctioneerError(err))
}
}
}
Expand Down Expand Up @@ -490,7 +482,7 @@ where
/// 6. Simulates the block to validate the payment.
/// 7. Saves the bid and inclusion proof to the auctioneer.
///
/// Implements this API: <https://chainbound.github.io/bolt-docs/api/relay#blocks_with_proofs>
/// Implements this API: <https://docs.boltprotocol.xyz/api/relay#blocks_with_proofs>
pub async fn submit_block_with_proofs(
Extension(api): Extension<Arc<BuilderApi<A, DB, S, G>>>,
req: Request<Body>,
Expand Down
10 changes: 5 additions & 5 deletions crates/api/src/constraints/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ where

/// Handles the submission of batch of signed constraints.
///
/// Implements this API: <https://chainbound.github.io/bolt-docs/api/builder#constraints>
/// Implements this API: <https://docs.boltprotocol.xyz/api/builder#constraints>
pub async fn submit_constraints(
Extension(api): Extension<Arc<ConstraintsApi<A, DB>>>,
req: Request<Body>,
Expand Down Expand Up @@ -138,7 +138,7 @@ where

/// Handles delegating constraint submission rights to another BLS key.
///
/// Implements this API: <https://chainbound.github.io/bolt-docs/api/builder#delegate>
/// Implements this API: <https://docs.boltprotocol.xyz/api/builder#delegate>
pub async fn delegate(
Extension(api): Extension<Arc<ConstraintsApi<A, DB>>>,
req: Request<Body>,
Expand Down Expand Up @@ -181,7 +181,7 @@ where

// Store the delegation in the database
tokio::spawn( async move {
if let Err(err) = api.db.save_validator_delegation(signed_delegation).await {
if let Err(err) = api.auctioneer.save_validator_delegation(signed_delegation).await {
error!(
error = %err,
"Failed to save delegation",
Expand All @@ -204,7 +204,7 @@ where

/// Handles revoking constraint submission rights from a BLS key.
///
/// Implements this API: <https://chainbound.github.io/bolt-docs/api/builder#revoke>
/// Implements this API: <https://docs.boltprotocol.xyz/api/builder#revoke>
pub async fn revoke(
Extension(api): Extension<Arc<ConstraintsApi<A, DB>>>,
req: Request<Body>,
Expand Down Expand Up @@ -247,7 +247,7 @@ where

// Store the delegation in the database
tokio::spawn( async move {
if let Err(err) = api.db.revoke_validator_delegation(signed_revocation).await {
if let Err(err) = api.auctioneer.revoke_validator_delegation(signed_revocation).await {
error!(
error = %err,
"Failed to do revocation",
Expand Down
2 changes: 1 addition & 1 deletion crates/api/src/proposer/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ where
///
/// The function returns a JSON response containing the best bid and inclusion proofs if found.
///
/// Implements this API: <https://chainbound.github.io/bolt-docs/api/builder#get_header_with_proofs>
/// Implements this API: <https://docs.boltprotocol.xyz/api/builder#get_header_with_proofs>
pub async fn get_header_with_proofs(
Extension(proposer_api): Extension<Arc<ProposerApi<A, DB, M, G>>>,
Path(GetHeaderParams { slot, parent_hash, public_key }): Path<GetHeaderParams>,
Expand Down
2 changes: 1 addition & 1 deletion crates/common/src/bid_submission/submission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ pub struct SignedBidSubmissionDeneb {
pub blobs_bundle: BlobsBundle,
pub signature: BlsSignature,
/// The Merkle proofs of inclusion as needed by the Constraints API.
/// Reference: <https://chainbound.github.io/bolt-docs/api/builder#get_header_with_proofs>
/// Reference: <https://docs.boltprotocol.xyz/api/builder#get_header_with_proofs>
#[serde(skip_serializing_if = "Option::is_none")]
pub proofs: Option<InclusionProofs>,
}
18 changes: 9 additions & 9 deletions crates/common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,23 +249,23 @@ pub enum Route {
BuilderBidsReceived,
ValidatorRegistration,

// Constraints API: Builder <https://chainbound.github.io/bolt-docs/api/builder>
/// Reference: <https://chainbound.github.io/bolt-docs/api/builder#constraints>
// Constraints API: Builder <https://docs.boltprotocol.xyz/api/builder>
/// Reference: <https://docs.boltprotocol.xyz/api/builder#constraints>
SubmitBuilderConstraints,
/// Reference: <https://chainbound.github.io/bolt-docs/api/builder#delegate>
/// Reference: <https://docs.boltprotocol.xyz/api/builder#delegate>
DelegateSubmissionRights,
/// Reference: <https://chainbound.github.io/bolt-docs/api/builder#revoke>
/// Reference: <https://docs.boltprotocol.xyz/api/builder#revoke>
RevokeSubmissionRights,
/// Reference: <https://chainbound.github.io/bolt-docs/api/builder#get_header_with_proofs>
/// Reference: <https://docs.boltprotocol.xyz/api/builder#get_header_with_proofs>
GetHeaderWithProofs,

// Constraints API: Relay <https://chainbound.github.io/bolt-docs/api/relay>
/// Reference: <https://chainbound.github.io/bolt-docs/api/relay#constraints>
// Constraints API: Relay <https://docs.boltprotocol.xyz/api/relay>
/// Reference: <https://docs.boltprotocol.xyz/api/relay#constraints>
GetBuilderConstraints,
/// Reference: <https://chainbound.github.io/bolt-docs/api/relay#constraints_stream>
/// Reference: <https://docs.boltprotocol.xyz/api/relay#constraints_stream>
GetBuilderConstraintsStream,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add missing documentation comment for GetBuilderDelegations

The GetBuilderDelegations route lacks a documentation comment with a reference link. For consistency and clarity, please add a /// Reference: comment pointing to the appropriate API documentation for this route.

GetBuilderDelegations,
/// Reference: <https://chainbound.github.io/bolt-docs/api/relay#blocks_with_proofs>
/// Reference: <https://docs.boltprotocol.xyz/api/relay#blocks_with_proofs>
SubmitBlockWithProofs,
}

Expand Down
3 changes: 0 additions & 3 deletions crates/database/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ pub enum DatabaseError {
#[error("Block submission not found")]
RowParsingError(#[from] Box<dyn std::error::Error + Sync + Send>),

#[error("Validator delegation not found")]
ValidatorDelegationNotFound,

#[error("General error")]
GeneralError,
}
32 changes: 0 additions & 32 deletions crates/database/src/mock_database_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,6 @@ impl MockDatabaseService {

#[async_trait]
impl DatabaseService for MockDatabaseService {
async fn get_validator_delegations(
&self,
pub_key: BlsPublicKey,
) -> Result<Vec<BlsPublicKey>, DatabaseError> {
let validator_delegations = self.validator_delegations.lock().unwrap();
let delegations = validator_delegations.get(&pub_key);
match delegations {
Some(delegations) => Ok(delegations.clone()),
None => Ok(vec![]),
}
}

async fn save_validator_delegation(
&self,
signed_delegation: SignedDelegation,
) -> Result<(), DatabaseError> {
// Add to the hashmap mapping
let mut validator_delegations = self.validator_delegations.lock().unwrap();
let delegatee_pub_key = signed_delegation.message.delegatee_pubkey;
let validator_pub_key = signed_delegation.message.validator_pubkey;
let delegations = validator_delegations.entry(validator_pub_key).or_insert_with(Vec::new);
delegations.push(delegatee_pub_key);
Ok(())
}
async fn revoke_validator_delegation(
&self,
signed_revocation: SignedRevocation,
) -> Result<(), DatabaseError> {
println!("received revocation: {:?}", signed_revocation);
Ok(())
}

async fn save_validator_registration(
&self,
_entry: ValidatorRegistrationInfo,
Expand Down
66 changes: 0 additions & 66 deletions crates/database/src/postgres/postgres_db_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,72 +365,6 @@ impl Default for PostgresDatabaseService {

#[async_trait]
impl DatabaseService for PostgresDatabaseService {
async fn get_validator_delegations(
&self,
validator_pubkey: BlsPublicKey, // Passing the validator pubkey as a byte slice
) -> Result<Vec<BlsPublicKey>, DatabaseError> {
match self
.pool
.get()
.await?
.query(
"
SELECT delegatee_pubkey
FROM validator_delegations
WHERE validator_pubkey = $1
",
&[&(validator_pubkey.as_ref())],
)
.await?
{
rows if rows.is_empty() => Err(DatabaseError::ValidatorDelegationNotFound),
rows => parse_rows(rows),
}
}

async fn save_validator_delegation(
&self,
signed_delegation: SignedDelegation,
) -> Result<(), DatabaseError> {
let mut client = self.pool.get().await?;
let transaction = client.transaction().await?;

let validator_pubkey = signed_delegation.message.validator_pubkey.as_ref();
let delegatee_pubkey = signed_delegation.message.delegatee_pubkey.as_ref();

transaction.execute(
"
INSERT INTO validator_delegations (validator_pubkey, delegatee_pubkey)
VALUES ($1, $2)
ON CONFLICT (validator_pubkey) DO UPDATE SET delegatee_pubkey = EXCLUDED.delegatee_pubkey
",
&[&validator_pubkey, &delegatee_pubkey],
).await?;

transaction.commit().await?;
Ok(())
}

async fn revoke_validator_delegation(
&self,
signed_revocation: SignedRevocation,
) -> Result<(), DatabaseError> {
let mut client = self.pool.get().await?;

let validator_pubkey = signed_revocation.message.validator_pubkey.as_ref();
let delegatee_pubkey = signed_revocation.message.delegatee_pubkey.as_ref();

client.execute(
"
DELETE FROM validator_delegations
WHERE validator_pubkey = $1 AND delegatee_pubkey = $2
",
&[&validator_pubkey, &delegatee_pubkey],
).await?;

Ok(())
}

async fn save_validator_registration(
&self,
registration_info: ValidatorRegistrationInfo,
Expand Down
15 changes: 0 additions & 15 deletions crates/database/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,6 @@ use crate::{

#[async_trait]
pub trait DatabaseService: Send + Sync + Clone {
async fn get_validator_delegations(
&self,
pub_key: BlsPublicKey,
) -> Result<Vec<BlsPublicKey>, DatabaseError>;

async fn save_validator_delegation(
&self,
signed_delegation: SignedDelegation,
) -> Result<(), DatabaseError>;

async fn revoke_validator_delegation(
&self,
signed_revocation: SignedRevocation,
) -> Result<(), DatabaseError>;

async fn save_validator_registration(
&self,
entry: ValidatorRegistrationInfo,
Expand Down
23 changes: 22 additions & 1 deletion crates/datastore/src/auctioneer/mock_auctioneer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use async_trait::async_trait;
use ethereum_consensus::primitives::{BlsPublicKey, Hash32, U256};

use helix_common::{
api::builder_api::TopBidUpdate, bid_submission::{
api::{builder_api::TopBidUpdate, constraints_api::{SignedDelegation, SignedRevocation}}, bid_submission::{
v2::header_submission::SignedHeaderSubmission, BidTrace, SignedBidSubmission,
}, eth::SignedBuilderBid, pending_block::PendingBlock, proofs::{InclusionProofs, SignedConstraintsWithProofData}, signing::RelaySigningContext, versioned_payload::PayloadAndBlobs, BuilderInfo, ProposerInfo
};
Expand Down Expand Up @@ -36,6 +36,27 @@ impl MockAuctioneer {

#[async_trait]
impl Auctioneer for MockAuctioneer {
async fn get_validator_delegations(
&self,
_pub_key: BlsPublicKey,
) -> Result<Vec<SignedDelegation>, AuctioneerError> {
Ok(vec![])
}

async fn save_validator_delegation(
&self,
_signed_delegation: SignedDelegation,
) -> Result<(), AuctioneerError> {
Ok(())
}

async fn revoke_validator_delegation(
&self,
_signed_revocation: SignedRevocation,
) -> Result<(), AuctioneerError> {
Ok(())
}

async fn save_constraints(
&self,
slot: u64,
Expand Down
19 changes: 17 additions & 2 deletions crates/datastore/src/auctioneer/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use std::collections::HashMap;
use async_trait::async_trait;
use ethereum_consensus::primitives::{BlsPublicKey, Hash32, U256};
use helix_common::{
api::builder_api::TopBidUpdate, bid_submission::{
api::{builder_api::TopBidUpdate, constraints_api::{SignedDelegation, SignedRevocation}}, bid_submission::{
v2::header_submission::SignedHeaderSubmission, BidTrace, SignedBidSubmission,
}, builder_info::BuilderInfo, eth::SignedBuilderBid, pending_block::PendingBlock, proofs::{SignedConstraintsWithProofData, InclusionProofs}, signing::RelaySigningContext, versioned_payload::PayloadAndBlobs, ProposerInfo
}, builder_info::BuilderInfo, eth::SignedBuilderBid, pending_block::PendingBlock, proofs::{InclusionProofs, SignedConstraintsWithProofData}, signing::RelaySigningContext, versioned_payload::PayloadAndBlobs, ProposerInfo
};
use helix_database::BuilderInfoDocument;

Expand All @@ -15,6 +15,21 @@ use tokio_stream::{Stream, StreamExt};
#[async_trait]
#[auto_impl::auto_impl(Arc)]
pub trait Auctioneer: Send + Sync + Clone {
async fn get_validator_delegations(
&self,
pub_key: BlsPublicKey,
) -> Result<Vec<SignedDelegation>, AuctioneerError>;
Comment on lines +18 to +21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider implementing pagination for get_validator_delegations

If the number of delegations can be large, returning all delegations at once may impact performance and memory usage. Consider implementing pagination or streaming results to handle large datasets efficiently.


async fn save_validator_delegation(
&self,
signed_delegation: SignedDelegation,
) -> Result<(), AuctioneerError>;

async fn revoke_validator_delegation(
&self,
signed_revocation: SignedRevocation,
) -> Result<(), AuctioneerError>;

async fn save_constraints(
&self,
slot: u64,
Expand Down
Loading