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: demo branch fixes #920

Merged
merged 36 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
077d10f
fix: demo branch fixes
matteojug Nov 22, 2024
fdde43c
update logging so we know what wsts messages came from where (#925)
xoloki Nov 22, 2024
b3f7f94
remove duplicate multisig addr check in sbtc-registry
cylewitruk Nov 22, 2024
47acf4f
also remove the map which is now unused
cylewitruk Nov 22, 2024
b062c52
make build
cylewitruk Nov 22, 2024
9afe522
explicitly add/remove peers to kademlia
cylewitruk Nov 22, 2024
258ef83
fmt
cylewitruk Nov 22, 2024
d206ed8
strip p2p info from peer addresses for kademlia
cylewitruk Nov 22, 2024
442fdab
took the wrong end of the multiaddr
cylewitruk Nov 22, 2024
07477b2
move kademlia addr adding
cylewitruk Nov 22, 2024
d3f322c
more logging
cylewitruk Nov 22, 2024
698a27b
try ignoring our own listening addresses for kad
cylewitruk Nov 22, 2024
3c8ddfa
still trying to get kad working
cylewitruk Nov 22, 2024
7de8b24
still working on kad
cylewitruk Nov 22, 2024
2947a9b
kad
cylewitruk Nov 22, 2024
63dc1e8
p2p tweaks + json logging
cylewitruk Nov 23, 2024
1bc3247
Pretty != pretty
cylewitruk Nov 23, 2024
562f58a
periodically log p2p peers
cylewitruk Nov 23, 2024
caa649b
use autonat v2
cylewitruk Nov 24, 2024
84d3bd5
log received messages on debug
cylewitruk Nov 24, 2024
7d07699
logging
cylewitruk Nov 24, 2024
8e66a64
comment kademlia stuff, some extra logs
matteojug Nov 24, 2024
2e8ec1a
re-enable kad & autonat + a little logging changes
cylewitruk Nov 25, 2024
7d3c210
early exit in 'handle_signer_message' to avoid performance issues
cylewitruk Nov 25, 2024
dbee9e0
WIP: c0ddb0b6 remove autonat etc from libp2p for now
cylewitruk Nov 25, 2024
01afe85
remove sleep
cylewitruk Nov 25, 2024
f6797d6
make build
cylewitruk Nov 25, 2024
3b8b8f6
bump signer dkgbegin timeout
cylewitruk Nov 25, 2024
a474a56
change some libp2p logs to trace
cylewitruk Nov 25, 2024
b5880c6
more logging tweaks
cylewitruk Nov 25, 2024
6fe9cf8
improve ignored message check formatting
cylewitruk Nov 25, 2024
ca98a84
fmt & remove extra cargo features
cylewitruk Nov 25, 2024
7d7c91b
signer logging stuff
cylewitruk Nov 25, 2024
8f788e8
use logging init fns
cylewitruk Nov 25, 2024
147f3f3
make dkg begin pause configurable-ish
cylewitruk Nov 25, 2024
de77a5e
refactor signer message filter
cylewitruk Nov 25, 2024
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
6 changes: 0 additions & 6 deletions contracts/contracts/sbtc-registry.clar
djordon marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,6 @@
;; stored to avoid replay
(define-map aggregate-pubkeys (buff 33) bool)

;; Data structure to store the current signer set,
;; stored to avoid replay
(define-map multi-sig-address principal bool)

;; Data structure to store the active protocol contracts
(define-map protocol-contracts principal bool)
(map-set protocol-contracts .sbtc-bootstrap-signers true)
Expand Down Expand Up @@ -304,8 +300,6 @@
(try! (is-protocol-caller))
;; Check that the aggregate pubkey is not already in the map
(asserts! (map-insert aggregate-pubkeys new-aggregate-pubkey true) ERR_AGG_PUBKEY_REPLAY)
;; Check that the new address (multi-sig) is not already in the map
(asserts! (map-insert multi-sig-address new-address true) ERR_MULTI_SIG_REPLAY)
;; Update the current signer set
(var-set current-signer-set new-keys)
;; Update the current multi-sig address
Expand Down
5 changes: 0 additions & 5 deletions contracts/tests/clarigen-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1116,11 +1116,6 @@ export const contracts = {
},
boolean
>,
multiSigAddress: {
name: "multi-sig-address",
key: "principal",
value: "bool",
} as TypedAbiMap<string, boolean>,
protocolContracts: {
name: "protocol-contracts",
key: "principal",
Expand Down
2 changes: 1 addition & 1 deletion signer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ tokio = { workspace = true, features = ["signal", "macros", "rt-multi-thread"] }
tokio-stream.workspace = true
tracing.workspace = true
tracing-attributes.workspace = true
tracing-subscriber.workspace = true
tracing-subscriber = { workspace = true }
url.workspace = true
# wsts.workspace = true
wsts = { git = "https://github.com/Trust-Machines/wsts.git", rev = "ebd7d7775ad5e44cdbf4f5c1fb468bdf6c467265" }
Expand Down
1 change: 1 addition & 0 deletions signer/src/emily_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ impl EmilyInteract for EmilyClient {
async fn set_chainstate(&self, chainstate: Chainstate) -> Result<Chainstate, Error> {
chainstate_api::set_chainstate(&self.config, chainstate)
.await
.inspect_err(|e| tracing::info!(?e, "Error for set_chainstate"))
djordon marked this conversation as resolved.
Show resolved Hide resolved
.map_err(EmilyClientError::AddChainstateEntry)
.map_err(Error::EmilyApi)
}
Expand Down
42 changes: 29 additions & 13 deletions signer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use axum::routing::post;
use axum::Router;
use cfg_if::cfg_if;
use clap::Parser;
use clap::ValueEnum;
use signer::api;
use signer::api::ApiState;
use signer::bitcoin::rpc::BitcoinCoreClient;
Expand All @@ -28,6 +29,12 @@ use signer::transaction_signer;
use signer::util::ApiFallbackClient;
use tokio::signal;

#[derive(Debug, Clone, Copy, ValueEnum)]
enum LogOutputFormat {
Json,
Pretty,
}

/// Command line arguments for the signer.
#[derive(Debug, Parser)]
#[clap(name = "sBTC Signer")]
Expand All @@ -41,22 +48,30 @@ struct SignerArgs {
/// pending migrations to the database on startup.
#[clap(long)]
migrate_db: bool,

#[clap(short = 'o', long = "output-format", default_value = "pretty")]
output_format: Option<LogOutputFormat>,
djordon marked this conversation as resolved.
Show resolved Hide resolved
}

#[tokio::main]
#[tracing::instrument(name = "signer")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize logging
// TODO(497): The whole logging thing should be revisited. We should support
// enabling different layers, i.e. for pretty console, for opentelem, etc.
//sbtc::logging::setup_logging("info,signer=debug", false);
let _ = tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.try_init();

// Parse the command line arguments.
let args = SignerArgs::parse();

// Initialize logging
let tracing_filter = tracing_subscriber::EnvFilter::from_default_env();
if let Some(LogOutputFormat::Json) = args.output_format {
tracing_subscriber::fmt()
.json()
.with_env_filter(tracing_filter)
.init();
djordon marked this conversation as resolved.
Show resolved Hide resolved
} else {
tracing_subscriber::fmt()
.with_env_filter(tracing_filter)
.init();
}

// Load the configuration file and/or environment variables.
let settings = Settings::new(args.config)?;

Expand Down Expand Up @@ -279,7 +294,7 @@ async fn run_transaction_signer(ctx: impl Context) -> Result<(), Error> {
network,
context: ctx.clone(),
context_window: 10000,
threshold: 2,
threshold: config.signer.bootstrap_signatures_required.into(),
rng: rand::thread_rng(),
signer_private_key: config.signer.private_key,
wsts_state_machines: HashMap::new(),
Expand All @@ -290,17 +305,18 @@ async fn run_transaction_signer(ctx: impl Context) -> Result<(), Error> {

/// Run the transaction coordinator event-loop.
async fn run_transaction_coordinator(ctx: impl Context) -> Result<(), Error> {
let private_key = ctx.config().signer.private_key;
let config = ctx.config().clone();
let private_key = config.signer.private_key;
let network = P2PNetwork::new(&ctx);

let coord = transaction_coordinator::TxCoordinatorEventLoop {
network,
context: ctx,
context_window: 10000,
private_key,
signing_round_max_duration: Duration::from_secs(15),
threshold: 2,
dkg_max_duration: Duration::from_secs(15),
signing_round_max_duration: Duration::from_secs(30),
threshold: config.signer.bootstrap_signatures_required,
dkg_max_duration: Duration::from_secs(120),
djordon marked this conversation as resolved.
Show resolved Hide resolved
sbtc_contracts_deployed: false,
is_epoch3: false,
};
Expand Down
146 changes: 122 additions & 24 deletions signer/src/network/libp2p/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use std::sync::Arc;
use std::time::Duration;

use futures::StreamExt;
use libp2p::multiaddr::Protocol;
use libp2p::swarm::SwarmEvent;
use libp2p::{gossipsub, identify, mdns, Swarm};
use libp2p::{gossipsub, identify, kad, mdns, Multiaddr, Swarm};
use tokio::sync::Mutex;

use crate::codec::{Decode, Encode};
Expand Down Expand Up @@ -95,7 +96,7 @@ pub async fn run(ctx: &impl Context, swarm: Arc<Mutex<Swarm<SignerBehavior>>>) {
tracing::warn!(%listener_id, %error, "Listener error");
}
SwarmEvent::Dialing { peer_id, connection_id } => {
tracing::info!(peer_id = ?peer_id, %connection_id, "Dialing peer");
tracing::trace!(?peer_id, %connection_id, "Dialing peer");
}
SwarmEvent::ConnectionEstablished { endpoint, peer_id, .. } => {
if !ctx.state().current_signer_set().is_allowed_peer(&peer_id) {
Expand All @@ -105,25 +106,25 @@ pub async fn run(ctx: &impl Context, swarm: Arc<Mutex<Swarm<SignerBehavior>>>) {
}
tracing::info!(%peer_id, ?endpoint, "Connected to peer");
}
SwarmEvent::ConnectionClosed { peer_id, cause, .. } => {
tracing::info!(%peer_id, ?cause, "Connection closed");
SwarmEvent::ConnectionClosed { peer_id, cause, endpoint, .. } => {
tracing::trace!(%peer_id, ?cause, ?endpoint, "Connection closed");
}
SwarmEvent::IncomingConnection { local_addr, send_back_addr, .. } => {
tracing::debug!(%local_addr, %send_back_addr, "Incoming connection");
tracing::trace!(%local_addr, %send_back_addr, "Incoming connection");
}
SwarmEvent::Behaviour(SignerBehaviorEvent::Ping(ping)) => {
tracing::trace!("ping received: {:?}", ping);
}
SwarmEvent::OutgoingConnectionError { connection_id, error, .. } => {
tracing::warn!(%connection_id, %error, "outgoing connection error");
SwarmEvent::OutgoingConnectionError { connection_id, error, peer_id } => {
tracing::trace!(%connection_id, %error, ?peer_id, "outgoing connection error");
}
SwarmEvent::IncomingConnectionError {
local_addr,
send_back_addr,
error,
..
} => {
tracing::warn!(%local_addr, %send_back_addr, %error, "incoming connection error");
tracing::trace!(%local_addr, %send_back_addr, %error, "incoming connection error");
}
SwarmEvent::NewExternalAddrCandidate { address } => {
tracing::debug!(%address, "New external address candidate");
Expand All @@ -135,19 +136,53 @@ pub async fn run(ctx: &impl Context, swarm: Arc<Mutex<Swarm<SignerBehavior>>>) {
tracing::debug!(%address, "External address expired");
}
SwarmEvent::NewExternalAddrOfPeer { peer_id, address } => {
tracing::debug!(%peer_id, %address, "New external address of peer");
if swarm.listeners().any(|addr| addr == &address) {
tracing::debug!(%peer_id, %address, "ignoring our own external address");
} else {
tracing::debug!(%peer_id, %address, "New external address of peer");
let kad_addr = strip_peer_id(&address);
tracing::debug!(%peer_id, %kad_addr, "Adding address to kademlia");
swarm
.behaviour_mut()
.kademlia
.add_address(&peer_id, kad_addr);
}
}
SwarmEvent::Behaviour(SignerBehaviorEvent::Kademlia(event)) => {
handle_kademlia_event(event);
}
SwarmEvent::Behaviour(SignerBehaviorEvent::AutonatClient(event)) => {
tracing::debug!(
tested_addr = ?event.tested_addr,
server = ?event.server,
result = ?event.result,
"autonat client event"
);
}
SwarmEvent::Behaviour(SignerBehaviorEvent::AutonatServer(event)) => {
tracing::debug!(
all_addrs = ?event.all_addrs,
tested_addr = ?event.tested_addr,
client = ?event.client,
result = ?event.result,
"autonat server event"
);
}
// The derived `SwarmEvent` is marked as #[non_exhaustive], so we must have a
// catch-all.
_ => tracing::trace!("unhandled swarm event"),
event => tracing::trace!(?event, "unhandled swarm event"),
}
}

// Drain the outbox and publish the messages to the network.
let outbox = outbox.lock().await.drain(..).collect::<Vec<_>>();
for payload in outbox {
tracing::info!("publishing message");
let msg_id = payload.id();
tracing::trace!(
message_id = hex::encode(msg_id),
msg = %payload,
"publishing message"
);

// Attempt to encode the message payload into bytes
// using the signer codec.
Expand Down Expand Up @@ -187,17 +222,49 @@ pub async fn run(ctx: &impl Context, swarm: Arc<Mutex<Swarm<SignerBehavior>>>) {
}
};

let log = async {
loop {
tokio::time::sleep(Duration::from_secs(60)).await;
let swarm = swarm.lock().await;
let peers = swarm.connected_peers().collect::<Vec<_>>();
tracing::debug!(?peers, "connected peers");
}
};

tokio::select! {
_ = term.wait_for_shutdown() => {
tracing::info!("libp2p received a termination signal; stopping the libp2p swarm");
},
_ = poll_outbound => {},
_ = poll_swarm => {},
_ = log => {},
}

tracing::info!("libp2p event loop terminated");
}

fn handle_kademlia_event(event: kad::Event) {
match event {
kad::Event::RoutingUpdated {
peer,
is_new_peer,
addresses,
bucket_range,
old_peer,
} => {
tracing::debug!(
%peer,
is_new_peer,
?addresses,
?bucket_range,
?old_peer,
"kademlia routing table updated"
);
}
_ => tracing::trace!(?event, "kademlia event"),
}
}

fn handle_mdns_event(swarm: &mut Swarm<SignerBehavior>, ctx: &impl Context, event: mdns::Event) {
use mdns::Event;

Expand Down Expand Up @@ -239,19 +306,18 @@ fn handle_mdns_event(swarm: &mut Swarm<SignerBehavior>, ctx: &impl Context, even

fn handle_identify_event(
swarm: &mut Swarm<SignerBehavior>,
ctx: &impl Context,
_: &impl Context,
event: identify::Event,
) {
use identify::Event;

match event {
Event::Received { peer_id, info, .. } => {
if !ctx.state().current_signer_set().is_allowed_peer(&peer_id) {
tracing::debug!(%peer_id, "ignoring identify message from unknown peer");
return;
}
tracing::debug!(%peer_id, "Received identify message from peer; adding to confirmed external addresses");
swarm.add_external_address(info.observed_addr.clone());
tracing::debug!(%peer_id, ?info, "Received identify message from peer");
swarm
.behaviour_mut()
.kademlia
.add_address(&peer_id, strip_peer_id(&info.observed_addr));
djordon marked this conversation as resolved.
Show resolved Hide resolved
}
Event::Pushed { connection_id, peer_id, info } => {
tracing::trace!(%connection_id, %peer_id, ?info, "Pushed identify message to peer");
Expand All @@ -275,21 +341,24 @@ fn handle_gossipsub_event(
match event {
Event::Message {
propagation_source: peer_id,
message_id: id,
message,
..
} => {
if !ctx.state().current_signer_set().is_allowed_peer(&peer_id) {
tracing::warn!(%peer_id, "ignoring message from unknown peer");
return;
}

tracing::trace!(local_peer_id = %swarm.local_peer_id(), %peer_id,
"Got message: '{}' with id: {id} from peer: {peer_id}",
hex::encode(&message.data),
);

Msg::decode(message.data.as_slice())
.map(|msg| {
tracing::trace!(
local_peer_id = %swarm.local_peer_id(),
%peer_id,
message_id = hex::encode(msg.id()),
%msg,
"received message",
);

let _ = ctx.get_signal_sender()
.send(P2PEvent::MessageReceived(msg).into())
.map_err(|error| {
Expand All @@ -311,3 +380,32 @@ fn handle_gossipsub_event(
}
}
}

/// For a multiaddr that ends with a peer id, this strips this suffix. Rust-libp2p
/// only supports dialing to an address without providing the peer id.
fn strip_peer_id(addr: &Multiaddr) -> Multiaddr {
let mut new_addr = Multiaddr::empty();
for protocol in addr.iter().take_while(|p| !matches!(p, Protocol::P2p(_))) {
new_addr.push(protocol);
}
new_addr
}

#[cfg(test)]
mod tests {
use std::str::FromStr;

use super::*;

#[test]
fn test_strip_peer_id() {
let endpoint =
"/ip4/198.51.100.0/tcp/4242/p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N";
let addr = Multiaddr::from_str(endpoint).unwrap();

let stripped = strip_peer_id(&addr);

let stripped_str = "/ip4/198.51.100.0/tcp/4242";
assert_eq!(stripped.to_string(), stripped_str);
}
}
Loading
Loading