Skip to content

Commit

Permalink
Merge pull request #9 from gattaca-com/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
gd-0 authored Jan 25, 2024
2 parents edfbed6 + d71db5f commit e324df5
Show file tree
Hide file tree
Showing 14 changed files with 210 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
REPO_NAME: ${{ secrets.REPO_NAME }}
run: |
IMAGE_NAME=latest
DOCKER_BUILDKIT=1 docker build -t helix:$IMAGE_NAME --build-arg AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID --build-arg AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY -f ./repos/$REPO_NAME/Dockerfile .
DOCKER_BUILDKIT=1 docker build -t helix:$IMAGE_NAME --build-arg AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID --build-arg AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY --build-arg REPO_NAME=$REPO_NAME -f ./repos/$REPO_NAME/Dockerfile .
DOCKER_BUILDKIT=1 docker tag helix:$IMAGE_NAME $REGISTRY_URL/helix:$IMAGE_NAME
DOCKER_BUILDKIT=1 docker login https://$REGISTRY_URL/ -u "$DOCKER_REG_USR" -p "$DOCKER_REG_PW"
DOCKER_BUILDKIT=1 docker push $REGISTRY_URL/helix:$IMAGE_NAME
5 changes: 3 additions & 2 deletions crates/api/src/builder/simulator/optimistic_simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl<A: Auctioneer + 'static, DB: DatabaseService + 'static> OptimisticSimulator
err=%err,
"Block simulation resulted in an error. Demoting builder...",
);
self.demote_builder_due_to_error(&request.message.builder_public_key, request.execution_payload.block_hash(), err.to_string()).await;
//self.demote_builder_due_to_error(&request.message.builder_public_key, request.execution_payload.block_hash(), err.to_string()).await;
}
}
return Err(err);
Expand Down Expand Up @@ -162,7 +162,8 @@ impl<A: Auctioneer, DB: DatabaseService> BlockSimulator for OptimisticSimulator<
) -> Result<bool, BlockSimError> {
let builder_info = self.fetch_builder_info(&request).await;

if self.should_process_optimistically(&request, &builder_info).await {
// if self.should_process_optimistically(&request, &builder_info).await {
if true {
debug!(
request_id=%request_id,
block_hash=%request.execution_payload.block_hash(),
Expand Down
35 changes: 28 additions & 7 deletions crates/api/src/proposer/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,15 +615,25 @@ where
},
};

// Calculate the remaining time needed to reach the target propagation duration.
// Conditionally pause the execution until we hit `TARGET_GET_PAYLOAD_PROPAGATION_DURATION_MS`
// to allow the block to propagate through the network.
let elapsed_since_propagate_start_ms = (get_nanos_timestamp()? - trace.beacon_client_broadcast) / 1_000_000;
let remaining_sleep_ms = self.target_get_payload_propagation_duration_ms.saturating_sub(elapsed_since_propagate_start_ms);
if remaining_sleep_ms > 0 && matches!(self.chain_info.network, Network::Mainnet) {
sleep(Duration::from_millis(remaining_sleep_ms)).await;
// Pause execution if the proposer is not whitelisted
let is_mainnet = matches!(self.chain_info.network, Network::Mainnet);
if is_mainnet && !self.is_trusted_proposer(&proposer_public_key).await? {
// Calculate the remaining time needed to reach the target propagation duration.
// Conditionally pause the execution until we hit `TARGET_GET_PAYLOAD_PROPAGATION_DURATION_MS`
// to allow the block to propagate through the network.
let elapsed_since_propagate_start_ms = (get_nanos_timestamp()? - trace.beacon_client_broadcast) / 1_000_000;
let remaining_sleep_ms = self.target_get_payload_propagation_duration_ms.saturating_sub(elapsed_since_propagate_start_ms);
if remaining_sleep_ms > 0 {
sleep(Duration::from_millis(remaining_sleep_ms)).await;
}
} else if !is_mainnet {
info!(request_id = %request_id, "not on mainnet, not pausing execution");
} else {
info!(request_id = %request_id, "proposer is not trusted, not pausing execution");
}



// Return response
info!(request_id = %request_id, trace = ?trace, timestamp = get_nanos_timestamp()?, "delivering payload");
Ok(get_payload_response)
Expand Down Expand Up @@ -974,6 +984,17 @@ where
}
});
}

async fn is_trusted_proposer(
&self,
public_key: &BlsPublicKey,
) -> Result<bool, ProposerApiError> {
Ok(self
.auctioneer
.get_trusted_proposers()
.await?
.map_or(false, |whitelist| whitelist.contains(public_key)))
}
}

async fn deserialize_get_payload_bytes(
Expand Down
23 changes: 23 additions & 0 deletions crates/common/src/proposer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use ethereum_consensus::{
primitives::{BlsPublicKey, Slot, ValidatorIndex},
serde::as_str,
};
use reth_primitives::revm_primitives::HashSet;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
Expand All @@ -23,3 +24,25 @@ pub struct ProposerSchedule {
pub validator_index: ValidatorIndex,
pub entry: SignedValidatorRegistration,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ProposerInfo {
pub name: String,
#[serde(rename = "pubkey")]
pub pub_key: BlsPublicKey,
}

impl From<Vec<ProposerInfo>> for ProposerInfoSet {
fn from(proposer_infos: Vec<ProposerInfo>) -> Self {
ProposerInfoSet(proposer_infos.into_iter().map(|info| info.pub_key).collect())
}
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ProposerInfoSet(HashSet<BlsPublicKey>);

impl ProposerInfoSet {
pub fn contains(&self, public_key: &BlsPublicKey) -> bool {
self.0.contains(public_key)
}
}
6 changes: 5 additions & 1 deletion crates/database/src/mock_database_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use ethereum_consensus::{
ssz::prelude::*,
types::mainnet::ExecutionPayload,
};
use helix_common::{api::proposer_api::ValidatorRegistrationInfo, GetHeaderTrace, bid_submission::v2::header_submission::SignedHeaderSubmission, HeaderSubmissionTrace, GossipedHeaderTrace, GossipedPayloadTrace, pending_block::PendingBlock, versioned_payload::PayloadAndBlobs};
use helix_common::{api::proposer_api::ValidatorRegistrationInfo, bid_submission::v2::header_submission::SignedHeaderSubmission, pending_block::PendingBlock, versioned_payload::PayloadAndBlobs, GetHeaderTrace, GossipedHeaderTrace, GossipedPayloadTrace, HeaderSubmissionTrace, ProposerInfo};
use helix_common::{
api::{builder_api::BuilderGetValidatorsResponseEntry, data_api::BidFilters},
bid_submission::{BidTrace, SignedBidSubmission},
Expand Down Expand Up @@ -256,4 +256,8 @@ impl DatabaseService for MockDatabaseService {
async fn remove_old_pending_blocks(&self) -> Result<(), DatabaseError> {
Ok(())
}

async fn get_trusted_proposers(&self) -> Result<Vec<ProposerInfo>, DatabaseError> {
Ok(vec![])
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE "trusted_proposers" (
"pub_key" bytea PRIMARY KEY,
"name" varchar,
"created_at" timestamptz DEFAULT (now())
);
18 changes: 13 additions & 5 deletions crates/database/src/postgres/postgres_db_row_parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ use ethereum_consensus::{
};
use thiserror::Error;
use helix_common::{
api::builder_api::BuilderGetValidatorsResponseEntry,
api::proposer_api::{ValidatorPreferences, ValidatorRegistrationInfo},
bellatrix::{ByteList, ByteVector, List},
bid_submission::BidTrace,
BuilderInfo, GetPayloadTrace, SignedValidatorRegistrationEntry, pending_block::PendingBlock,
api::builder_api::BuilderGetValidatorsResponseEntry, api::proposer_api::{ValidatorPreferences, ValidatorRegistrationInfo}, bellatrix::{ByteList, ByteVector, List}, bid_submission::BidTrace, pending_block::PendingBlock, BuilderInfo, GetPayloadTrace, ProposerInfo, SignedValidatorRegistrationEntry
};

use crate::{
Expand Down Expand Up @@ -258,6 +254,18 @@ impl FromRow for SignedValidatorRegistrationEntry {
}
}

impl FromRow for ProposerInfo {
fn from_row(row: &tokio_postgres::Row) -> Result<Self, DatabaseError>
where
Self: Sized,
{
Ok(ProposerInfo {
name: row.get::<&str, &str>("name").to_string(),
pub_key: parse_bytes_to_pubkey(row.get::<&str, &[u8]>("pub_key"))?,
})
}
}

pub fn parse_timestamptz_to_u64(timestamp: std::time::SystemTime) -> Result<u64, DatabaseError> {
timestamp
.duration_since(std::time::UNIX_EPOCH)
Expand Down
22 changes: 17 additions & 5 deletions crates/database/src/postgres/postgres_db_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ use helix_common::{
api::{
builder_api::BuilderGetValidatorsResponseEntry, data_api::BidFilters,
proposer_api::ValidatorRegistrationInfo,
},
bid_submission::{BidTrace, SignedBidSubmission, v2::header_submission::SignedHeaderSubmission, BidSubmission},
simulator::BlockSimError,
BuilderInfo, GetPayloadTrace, RelayConfig, SignedValidatorRegistrationEntry,
SubmissionTrace, ValidatorSummary, GetHeaderTrace, HeaderSubmissionTrace, GossipedPayloadTrace, GossipedHeaderTrace, pending_block::PendingBlock, versioned_payload::PayloadAndBlobs,
}, bid_submission::{BidTrace, SignedBidSubmission, v2::header_submission::SignedHeaderSubmission, BidSubmission}, pending_block::PendingBlock, simulator::BlockSimError, versioned_payload::PayloadAndBlobs, BuilderInfo, GetHeaderTrace, GetPayloadTrace, GossipedHeaderTrace, GossipedPayloadTrace, HeaderSubmissionTrace, ProposerInfo, RelayConfig, SignedValidatorRegistrationEntry, SubmissionTrace, ValidatorSummary
};
use tokio_postgres::{types::ToSql, NoTls};
use tracing::{error, info};
Expand Down Expand Up @@ -1425,4 +1421,20 @@ impl DatabaseService for PostgresDatabaseService {

Ok(())
}

async fn get_trusted_proposers(
&self,
) -> Result<Vec<ProposerInfo>, DatabaseError> {
parse_rows(self.pool
.get()
.await?
.query(
"
SELECT * FROM trusted_proposers
",
&[],
)
.await?
)
}
}
8 changes: 3 additions & 5 deletions crates/database/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ use helix_common::{
api::{
builder_api::BuilderGetValidatorsResponseEntry, data_api::BidFilters,
proposer_api::ValidatorRegistrationInfo,
},
bid_submission::{BidTrace, SignedBidSubmission, v2::header_submission::SignedHeaderSubmission},
builder_info::BuilderInfo,
simulator::BlockSimError,
GetPayloadTrace, SignedValidatorRegistrationEntry, SubmissionTrace, ValidatorSummary, GetHeaderTrace, HeaderSubmissionTrace, GossipedHeaderTrace, GossipedPayloadTrace, pending_block::PendingBlock, versioned_payload::PayloadAndBlobs,
}, bid_submission::{BidTrace, SignedBidSubmission, v2::header_submission::SignedHeaderSubmission}, builder_info::BuilderInfo, pending_block::PendingBlock, simulator::BlockSimError, versioned_payload::PayloadAndBlobs, GetHeaderTrace, GetPayloadTrace, GossipedHeaderTrace, GossipedPayloadTrace, HeaderSubmissionTrace, ProposerInfo, SignedValidatorRegistrationEntry, SubmissionTrace, ValidatorSummary
};

use crate::{
Expand Down Expand Up @@ -177,4 +173,6 @@ pub trait DatabaseService: Send + Sync + Clone {
async fn get_pending_blocks(&self) -> Result<Vec<PendingBlock>, DatabaseError>;

async fn remove_old_pending_blocks(&self) -> Result<(), DatabaseError>;

async fn get_trusted_proposers(&self) -> Result<Vec<ProposerInfo>, DatabaseError>;
}
14 changes: 14 additions & 0 deletions crates/datastore/src/auctioneer/mock_auctioneer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use async_trait::async_trait;
use ethereum_consensus::primitives::{BlsPublicKey, Hash32, U256};

use helix_common::versioned_payload::PayloadAndBlobs;
use helix_common::{ProposerInfo, ProposerInfoSet};
use helix_database::types::BuilderInfoDocument;
use helix_common::{signing::RelaySigningContext, bid_submission::v2::header_submission::SignedHeaderSubmission};
use helix_common::{
Expand Down Expand Up @@ -213,4 +214,17 @@ impl Auctioneer for MockAuctioneer {
) -> Result<Option<SignedBuilderBid>, AuctioneerError> {
Ok(None)
}

async fn update_trusted_proposers(
&self,
_proposer_whitelist: Vec<ProposerInfo>,
) -> Result<(), AuctioneerError> {
Ok(())
}

async fn get_trusted_proposers(
&self,
) -> Result<Option<ProposerInfoSet>, AuctioneerError> {
Ok(Some(ProposerInfoSet::from(vec![])))
}
}
12 changes: 8 additions & 4 deletions crates/datastore/src/auctioneer/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ use async_trait::async_trait;
use ethereum_consensus::primitives::{BlsPublicKey, Hash32, U256};
use helix_database::BuilderInfoDocument;
use helix_common::{
bid_submission::{BidTrace, SignedBidSubmission, v2::header_submission::SignedHeaderSubmission},
builder_info::BuilderInfo,
eth::SignedBuilderBid,
signing::RelaySigningContext, versioned_payload::PayloadAndBlobs,
bid_submission::{BidTrace, SignedBidSubmission, v2::header_submission::SignedHeaderSubmission}, builder_info::BuilderInfo, eth::SignedBuilderBid, signing::RelaySigningContext, versioned_payload::PayloadAndBlobs, ProposerInfo, ProposerInfoSet
};

use crate::{error::AuctioneerError, types::SaveBidAndUpdateTopBidResponse};
Expand Down Expand Up @@ -143,4 +140,11 @@ pub trait Auctioneer: Send + Sync + Clone {
state: &mut SaveBidAndUpdateTopBidResponse,
signing_context: &RelaySigningContext,
) -> Result<Option<SignedBuilderBid>, AuctioneerError>;

async fn update_trusted_proposers(
&self,
proposer_whitelist: Vec<ProposerInfo>,
) -> Result<(), AuctioneerError>;

async fn get_trusted_proposers(&self) -> Result<Option<ProposerInfoSet>, AuctioneerError>;
}
20 changes: 18 additions & 2 deletions crates/datastore/src/redis/redis_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ethereum_consensus::{
primitives::{BlsPublicKey, Hash32},
ssz::prelude::*,
};
use helix_common::{bid_submission::BidSubmission, versioned_payload::PayloadAndBlobs};
use helix_common::{bid_submission::BidSubmission, versioned_payload::PayloadAndBlobs, ProposerInfo, ProposerInfoSet};
use helix_common::bid_submission::v2::header_submission::SignedHeaderSubmission;
use redis::AsyncCommands;
use serde::{de::DeserializeOwned, Serialize};
Expand All @@ -30,7 +30,7 @@ use crate::{
},
types::{
keys::{
BUILDER_INFO_KEY, LAST_HASH_DELIVERED_KEY, LAST_SLOT_DELIVERED_KEY,
BUILDER_INFO_KEY, LAST_HASH_DELIVERED_KEY, LAST_SLOT_DELIVERED_KEY, PROPOSER_WHITELIST_KEY
},
SaveBidAndUpdateTopBidResponse,
},
Expand Down Expand Up @@ -748,6 +748,22 @@ impl Auctioneer for RedisCache {

Ok(Some(builder_bid))
}

async fn update_trusted_proposers(
&self,
proposer_whitelist: Vec<ProposerInfo>,
) -> Result<(), AuctioneerError> {
let proposer_whitelist_map: ProposerInfoSet = proposer_whitelist.into();
self.set(PROPOSER_WHITELIST_KEY, &proposer_whitelist_map, None)
.await?;

Ok(())
}

async fn get_trusted_proposers(&self) -> Result<Option<ProposerInfoSet>, AuctioneerError> {
let proposer_whitelist_map = self.get(PROPOSER_WHITELIST_KEY).await?;
Ok(proposer_whitelist_map)
}
}

fn get_top_bid(bid_values: &HashMap<String, U256>) -> Option<(String, U256)> {
Expand Down
1 change: 1 addition & 0 deletions crates/datastore/src/types/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub const BID_FLOOR_VALUE_KEY: &str = "bid-floor-value";
pub const EXEC_PAYLOAD_KEY: &str = "cache-exec-payload";
pub const BUILDER_INFO_KEY: &str = "builder-info";
pub const SEEN_BLOCK_HASHES_KEY: &str = "seen-block-hashes";
pub const PROPOSER_WHITELIST_KEY: &str = "proposer-whitelist";

// Database
pub const VALIDATOR_REGISTRATIONS_KEY: &str = "validator-registrations";
Expand Down
Loading

0 comments on commit e324df5

Please sign in to comment.