Skip to content

Commit

Permalink
feat: Report git commit hash as agent metadata (hyperlane-xyz#4282)
Browse files Browse the repository at this point in the history
### Description

* We are storing git commit hash as an environment variable when we
compile the source code of an agent.
* Validator uses git commit hash as a agent version in
`metadata_latest.json` file.
* File `metadata_latest.json` is overwritten every time when validator
is restarted.
* Git commit hash is extracted by `git` util, so, it should be available
during build time.
* If the directory with the source code does not contain `.git` folder,
git commit hash will be defaulted to `VERGEN_IDEMPOTENT_OUTPUT`.

Agent Metadata is propagated to Relayer and Scraper, but is not used
there. We can use it in the future, reporting git hash commit in the
logs, for example.

### Backward compatibility

Yes

### Testing

* Tested locally with E2E Tests.
* Tested against S3 by deploying docker image into k8s

---------

Co-authored-by: Danil Nemirovsky <[email protected]>
  • Loading branch information
ameten and ameten authored Aug 12, 2024
1 parent 7625bf8 commit d1bf212
Show file tree
Hide file tree
Showing 23 changed files with 440 additions and 241 deletions.
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ typescript/hyperlane-deploy/.env
**/*.swp
**/*.swo

rust
tmp.env
.DS_STORE

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./rust
context: .
file: ./rust/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
Expand Down
17 changes: 17 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 22 additions & 16 deletions rust/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,24 @@ RUN apt-get update && \
apt-get install -y musl-tools clang && \
rustup target add x86_64-unknown-linux-musl

# Add workspace to workdir
COPY agents ./agents
COPY chains ./chains
COPY hyperlane-base ./hyperlane-base
COPY hyperlane-core ./hyperlane-core
COPY hyperlane-test ./hyperlane-test
COPY ethers-prometheus ./ethers-prometheus
COPY utils ./utils
COPY sealevel ./sealevel

COPY Cargo.toml .
COPY Cargo.lock .
RUN mkdir rust

# Add workspace to workdir
COPY rust/agents rust/agents
COPY rust/chains rust/chains
COPY rust/hyperlane-base rust/hyperlane-base
COPY rust/hyperlane-core rust/hyperlane-core
COPY rust/hyperlane-test rust/hyperlane-test
COPY rust/ethers-prometheus rust/ethers-prometheus
COPY rust/utils rust/utils
COPY rust/sealevel rust/sealevel

COPY rust/Cargo.toml rust/.
COPY rust/Cargo.lock rust/.

COPY .git .git

WORKDIR /usr/src/rust

# Build binaries
RUN \
Expand All @@ -29,9 +35,9 @@ RUN \
--mount=id=cargo-home-git,type=cache,sharing=locked,target=/usr/local/cargo/git \
RUSTFLAGS="--cfg tokio_unstable" cargo build --release --bin validator --bin relayer --bin scraper && \
mkdir -p /release && \
cp /usr/src/target/release/validator /release && \
cp /usr/src/target/release/relayer /release && \
cp /usr/src/target/release/scraper /release
cp /usr/src/rust/target/release/validator /release && \
cp /usr/src/rust/target/release/relayer /release && \
cp /usr/src/rust/target/release/scraper /release

## 2: Copy the binaries to release image
FROM ubuntu:22.04
Expand All @@ -43,7 +49,7 @@ RUN apt-get update && \
rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY config ./config
COPY rust/config ./config
COPY --from=builder /release/* .

RUN chmod 777 /app && \
Expand Down
5 changes: 3 additions & 2 deletions rust/agents/relayer/src/relayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use hyperlane_base::{
db::{HyperlaneRocksDB, DB},
metrics::{AgentMetrics, MetricsUpdater},
settings::ChainConf,
BaseAgent, ChainMetrics, ContractSyncMetrics, ContractSyncer, CoreMetrics, HyperlaneAgentCore,
SyncOptions,
AgentMetadata, BaseAgent, ChainMetrics, ContractSyncMetrics, ContractSyncer, CoreMetrics,
HyperlaneAgentCore, SyncOptions,
};
use hyperlane_core::{
HyperlaneDomain, HyperlaneMessage, InterchainGasPayment, MerkleTreeInsertion, QueueOperation,
Expand Down Expand Up @@ -113,6 +113,7 @@ impl BaseAgent for Relayer {
type Settings = RelayerSettings;

async fn from_settings(
_agent_metadata: AgentMetadata,
settings: Self::Settings,
core_metrics: Arc<CoreMetrics>,
agent_metrics: AgentMetrics,
Expand Down
5 changes: 3 additions & 2 deletions rust/agents/scraper/src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use async_trait::async_trait;
use derive_more::AsRef;
use futures::future::try_join_all;
use hyperlane_base::{
broadcast::BroadcastMpscSender, metrics::AgentMetrics, settings::IndexSettings, BaseAgent,
ChainMetrics, ContractSyncMetrics, ContractSyncer, CoreMetrics, HyperlaneAgentCore,
broadcast::BroadcastMpscSender, metrics::AgentMetrics, settings::IndexSettings, AgentMetadata,
BaseAgent, ChainMetrics, ContractSyncMetrics, ContractSyncer, CoreMetrics, HyperlaneAgentCore,
MetricsUpdater, SyncOptions,
};
use hyperlane_core::{Delivery, HyperlaneDomain, HyperlaneMessage, InterchainGasPayment, H512};
Expand Down Expand Up @@ -41,6 +41,7 @@ impl BaseAgent for Scraper {
type Settings = ScraperSettings;

async fn from_settings(
_agent_metadata: AgentMetadata,
settings: Self::Settings,
metrics: Arc<CoreMetrics>,
agent_metrics: AgentMetrics,
Expand Down
20 changes: 18 additions & 2 deletions rust/agents/validator/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use hyperlane_base::{
db::{HyperlaneRocksDB, DB},
metrics::AgentMetrics,
settings::ChainConf,
BaseAgent, ChainMetrics, CheckpointSyncer, ContractSyncMetrics, ContractSyncer, CoreMetrics,
HyperlaneAgentCore, MetricsUpdater, SequencedDataContractSync,
AgentMetadata, BaseAgent, ChainMetrics, CheckpointSyncer, ContractSyncMetrics, ContractSyncer,
CoreMetrics, HyperlaneAgentCore, MetricsUpdater, SequencedDataContractSync,
};

use hyperlane_core::{
Expand Down Expand Up @@ -50,6 +50,7 @@ pub struct Validator {
core_metrics: Arc<CoreMetrics>,
agent_metrics: AgentMetrics,
chain_metrics: ChainMetrics,
agent_metadata: AgentMetadata,
}

#[async_trait]
Expand All @@ -59,6 +60,7 @@ impl BaseAgent for Validator {
type Settings = ValidatorSettings;

async fn from_settings(
agent_metadata: AgentMetadata,
settings: Self::Settings,
metrics: Arc<CoreMetrics>,
agent_metrics: AgentMetrics,
Expand Down Expand Up @@ -123,6 +125,7 @@ impl BaseAgent for Validator {
agent_metrics,
chain_metrics,
core_metrics: metrics,
agent_metadata,
})
}

Expand Down Expand Up @@ -169,6 +172,11 @@ impl BaseAgent for Validator {
.instrument(info_span!("MetricsUpdater")),
);

// report agent metadata
self.metadata()
.await
.expect("Failed to report agent metadata");

// announce the validator after spawning the signer task
self.announce().await.expect("Failed to announce validator");

Expand Down Expand Up @@ -290,6 +298,14 @@ impl Validator {
}
}

async fn metadata(&self) -> Result<()> {
self.checkpoint_syncer
.write_metadata(&self.agent_metadata)
.await?;

Ok(())
}

async fn announce(&self) -> Result<()> {
let address = self.signer.eth_address();
let announcement_location = self.checkpoint_syncer.announcement_location();
Expand Down
4 changes: 4 additions & 0 deletions rust/hyperlane-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ tempfile.workspace = true
tracing-test.workspace = true
walkdir.workspace = true

[build-dependencies]
anyhow = { workspace = true }
vergen = { version = "8.3.2", features = ["build", "git", "gitcl"] }

[features]
default = ["oneline-errors", "color-eyre"]
oneline-eyre = ["backtrace-oneline", "backtrace"]
Expand Down
8 changes: 8 additions & 0 deletions rust/hyperlane-base/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use anyhow::Result;
use vergen::EmitBuilder;

fn main() -> Result<()> {
EmitBuilder::builder().git_sha(false).emit()?;

Ok(())
}
11 changes: 11 additions & 0 deletions rust/hyperlane-base/src/agent.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub use crate::metadata::AgentMetadata;

use std::{env, fmt::Debug, sync::Arc};

use async_trait::async_trait;
Expand Down Expand Up @@ -40,6 +42,7 @@ pub trait BaseAgent: Send + Sync + Debug {

/// Instantiate the agent from the standard settings object
async fn from_settings(
agent_metadata: AgentMetadata,
settings: Self::Settings,
metrics: Arc<CoreMetrics>,
agent_metrics: AgentMetrics,
Expand Down Expand Up @@ -72,6 +75,13 @@ pub async fn agent_main<A: BaseAgent>() -> Result<()> {
color_eyre::install()?;
}

// Latest git commit hash at the time when agent was built.
// If .git was not present at the time of build,
// the variable defaults to "VERGEN_IDEMPOTENT_OUTPUT".
let git_sha = env!("VERGEN_GIT_SHA").to_owned();

let agent_metadata = AgentMetadata::new(git_sha);

let settings = A::Settings::load()?;
let core_settings: &Settings = settings.as_ref();

Expand All @@ -80,6 +90,7 @@ pub async fn agent_main<A: BaseAgent>() -> Result<()> {
let agent_metrics = create_agent_metrics(&metrics)?;
let chain_metrics = create_chain_metrics(&metrics)?;
let agent = A::from_settings(
agent_metadata,
settings,
metrics.clone(),
agent_metrics,
Expand Down
2 changes: 2 additions & 0 deletions rust/hyperlane-base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub use agent::*;
/// The local database used by agents
pub mod db;

mod metadata;

pub mod metrics;
pub use metrics::*;

Expand Down
9 changes: 9 additions & 0 deletions rust/hyperlane-base/src/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use derive_new::new;
use serde::{Deserialize, Serialize};

/// Metadata about agent
#[derive(Debug, Deserialize, Serialize, new)]
pub struct AgentMetadata {
/// Contains git commit hash of the agent binary
pub git_sha: String,
}
3 changes: 3 additions & 0 deletions rust/hyperlane-base/src/traits/checkpoint_syncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::fmt::Debug;
use async_trait::async_trait;
use eyre::Result;

use crate::AgentMetadata;
use hyperlane_core::{SignedAnnouncement, SignedCheckpointWithMessageId};

/// A generic trait to read/write Checkpoints offchain
Expand All @@ -27,6 +28,8 @@ pub trait CheckpointSyncer: Debug + Send + Sync {
&self,
signed_checkpoint: &SignedCheckpointWithMessageId,
) -> Result<()>;
/// Write the agent metadata to this syncer
async fn write_metadata(&self, metadata: &AgentMetadata) -> Result<()>;
/// Write the signed announcement to this syncer
async fn write_announcement(&self, signed_announcement: &SignedAnnouncement) -> Result<()>;
/// Return the announcement storage location for this syncer
Expand Down
12 changes: 11 additions & 1 deletion rust/hyperlane-base/src/types/gcs_storage.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::CheckpointSyncer;
use crate::{AgentMetadata, CheckpointSyncer};
use async_trait::async_trait;
use derive_new::new;
use eyre::{bail, Result};
Expand All @@ -7,6 +7,7 @@ use std::fmt;
use ya_gcp::{storage::StorageClient, AuthFlow, ClientBuilder, ClientBuilderConfig};

const LATEST_INDEX_KEY: &str = "gcsLatestIndexKey";
const METADATA_KEY: &str = "gcsMetadataKey";
const ANNOUNCEMENT_KEY: &str = "gcsAnnouncementKey";
/// Path to GCS users_secret file
pub const GCS_USER_SECRET: &str = "GCS_USER_SECRET";
Expand Down Expand Up @@ -174,6 +175,15 @@ impl CheckpointSyncer for GcsStorageClient {
Ok(())
}

/// Write the agent metadata to this syncer
async fn write_metadata(&self, metadata: &AgentMetadata) -> Result<()> {
let serialized_metadata = serde_json::to_string_pretty(metadata)?;
self.inner
.insert_object(&self.bucket, METADATA_KEY, serialized_metadata)
.await?;
Ok(())
}

/// Write the signed announcement to this syncer
async fn write_announcement(&self, signed_announcement: &SignedAnnouncement) -> Result<()> {
self.inner
Expand Down
17 changes: 15 additions & 2 deletions rust/hyperlane-base/src/types/local_storage.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::path::PathBuf;

use crate::traits::CheckpointSyncer;
use crate::AgentMetadata;
use async_trait::async_trait;
use eyre::{Context, Result};
use hyperlane_core::{SignedAnnouncement, SignedCheckpointWithMessageId};
use prometheus::IntGauge;

use crate::traits::CheckpointSyncer;

#[derive(Debug, Clone)]
/// Type for reading/write to LocalStorage
pub struct LocalStorage {
Expand Down Expand Up @@ -40,6 +40,10 @@ impl LocalStorage {
fn announcement_file_path(&self) -> PathBuf {
self.path.join("announcement.json")
}

fn metadata_file_path(&self) -> PathBuf {
self.path.join("metadata_latest.json")
}
}

#[async_trait]
Expand Down Expand Up @@ -91,6 +95,15 @@ impl CheckpointSyncer for LocalStorage {
Ok(())
}

async fn write_metadata(&self, metadata: &AgentMetadata) -> Result<()> {
let serialized_metadata = serde_json::to_string_pretty(metadata)?;
let path = self.metadata_file_path();
tokio::fs::write(&path, &serialized_metadata)
.await
.with_context(|| format!("Writing agent metadata to {path:?}"))?;
Ok(())
}

async fn write_announcement(&self, signed_announcement: &SignedAnnouncement) -> Result<()> {
let serialized_announcement = serde_json::to_string_pretty(signed_announcement)?;
let path = self.announcement_file_path();
Expand Down
Loading

0 comments on commit d1bf212

Please sign in to comment.