● Fix CI formatting, add salvium-cli to CI, pre-commit hook

- cargo fmt fixes (transport.rs, wire_format.rs, miner main.rs)
  - Add salvium-cli compile check + salvium-wallet full test to CI
  - Pre-commit hook: fmt --check + clippy -Dwarnings matching CI
  - Update TODO.md: multisig ~98%, CI gaps all resolved
This commit is contained in:
Matt Hess
2026-02-25 18:59:37 +00:00
parent d8bc05b018
commit d4723bc7e0
5 changed files with 35 additions and 56 deletions
+5 -3
View File
@@ -85,17 +85,19 @@ jobs:
run: cargo test -p salvium-crypto --test '*' -- --nocapture
test-wallet:
name: "Test: wallet + transactions"
name: "Test: wallet + transactions + CLI"
needs: [compile]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: salvium-wallet
run: cargo test -p salvium-wallet --lib -- --nocapture
- name: salvium-wallet (unit + integration compile)
run: cargo test -p salvium-wallet -- --nocapture
- name: salvium-tx
run: cargo test -p salvium-tx -- --nocapture
- name: salvium-cli (compile check)
run: cargo test -p salvium-cli -- --nocapture
test-infra:
name: "Test: miner + multisig + RPC"
+7 -3
View File
@@ -73,7 +73,12 @@ fn main() {
let args = Args::parse();
if args.ipc {
salvium_miner::ipc::run_ipc(args.threads, args.light, !args.no_large_pages, args.no_affinity);
salvium_miner::ipc::run_ipc(
args.threads,
args.light,
!args.no_large_pages,
args.no_affinity,
);
return;
}
@@ -110,7 +115,7 @@ fn run_benchmark(args: &Args) {
blob[0] = 10; // major version
blob[1] = 10; // minor version
blob[2] = 1; // timestamp (varint = 1)
// bytes 3..35 = prev_hash (zeros), bytes 35..39 = nonce, rest = zeros
// bytes 3..35 = prev_hash (zeros), bytes 35..39 = nonce, rest = zeros
engine.send_job(MiningJob {
job_id: 0,
@@ -714,7 +719,6 @@ fn run_daemon(args: &Args) {
est_block
);
last_stats = Instant::now();
}
std::thread::sleep(Duration::from_millis(50));
+17 -32
View File
@@ -159,9 +159,7 @@ impl Coordinator {
/// Accept connections from `expected_signers - 1` clients.
///
/// Returns the listener and the connected streams.
pub async fn accept_signers(
&self,
) -> Result<(TcpListener, Vec<TcpStream>), String> {
pub async fn accept_signers(&self) -> Result<(TcpListener, Vec<TcpStream>), String> {
let listener = TcpListener::bind(&self.config.bind_addr)
.await
.map_err(|e| format!("bind failed: {}", e))?;
@@ -210,10 +208,7 @@ impl Coordinator {
for stream in streams.iter_mut() {
let wire_msg = recv_message(stream).await?;
if wire_msg.msg_type != MsgType::Kex {
return Err(format!(
"expected Kex message, got {:?}",
wire_msg.msg_type
));
return Err(format!("expected Kex message, got {:?}", wire_msg.msg_type));
}
messages.push(wire_msg.payload);
}
@@ -356,27 +351,24 @@ impl SignerClient {
// First receive the Ready message with count
let ready = recv_message(&mut self.stream).await?;
if ready.msg_type != MsgType::Ready {
return Err(format!(
"expected Ready message, got {:?}",
ready.msg_type
));
return Err(format!("expected Ready message, got {:?}", ready.msg_type));
}
if ready.payload.len() < 4 {
return Err("Ready message payload too short".to_string());
}
let count =
u32::from_le_bytes([ready.payload[0], ready.payload[1], ready.payload[2], ready.payload[3]])
as usize;
let count = u32::from_le_bytes([
ready.payload[0],
ready.payload[1],
ready.payload[2],
ready.payload[3],
]) as usize;
// Receive each KEX message
let mut messages = Vec::with_capacity(count);
for _ in 0..count {
let wire_msg = recv_message(&mut self.stream).await?;
if wire_msg.msg_type != MsgType::Kex {
return Err(format!(
"expected Kex message, got {:?}",
wire_msg.msg_type
));
return Err(format!("expected Kex message, got {:?}", wire_msg.msg_type));
}
messages.push(wire_msg.payload);
}
@@ -482,13 +474,10 @@ mod tests {
// Coordinator's own message
let local = b"coordinator_kex_data".to_vec();
let messages = Coordinator::collect_kex_round(
&mut streams,
Some(&local),
Duration::from_secs(5),
)
.await
.unwrap();
let messages =
Coordinator::collect_kex_round(&mut streams, Some(&local), Duration::from_secs(5))
.await
.unwrap();
assert_eq!(messages.len(), 3); // 1 local + 2 clients
messages
@@ -543,13 +532,9 @@ mod tests {
let mut streams = vec![stream1, stream2];
// Client 0 (index 0) is the proposer
let tx_data = Coordinator::exchange_tx_set(
&mut streams,
0,
Duration::from_secs(5),
)
.await
.unwrap();
let tx_data = Coordinator::exchange_tx_set(&mut streams, 0, Duration::from_secs(5))
.await
.unwrap();
assert_eq!(tx_data, b"test_tx_set_binary_data");
tx_data
+3 -10
View File
@@ -224,10 +224,7 @@ pub fn decode_tx_set(data: &[u8]) -> Result<MultisigTxSet, String> {
.as_object()
.ok_or_else(|| "expected object".to_string())?;
let threshold = obj
.get("threshold")
.and_then(|v| v.as_u64())
.unwrap_or(0) as usize;
let threshold = obj.get("threshold").and_then(|v| v.as_u64()).unwrap_or(0) as usize;
let signer_count = obj
.get("signer_count")
.and_then(|v| v.as_u64())
@@ -298,16 +295,12 @@ fn encode_pending_tx(tx: &PendingMultisigTx) -> PsValue {
PsValue::String(contexts_json),
);
let nonces_json =
serde_json::to_vec(&tx.input_nonces).expect("input_nonces serialization");
let nonces_json = serde_json::to_vec(&tx.input_nonces).expect("input_nonces serialization");
map.insert("input_nonces".to_string(), PsValue::String(nonces_json));
let partials_json =
serde_json::to_vec(&tx.input_partials).expect("input_partials serialization");
map.insert(
"input_partials".to_string(),
PsValue::String(partials_json),
);
map.insert("input_partials".to_string(), PsValue::String(partials_json));
PsValue::Object(map)
}
+3 -8
View File
@@ -1179,10 +1179,7 @@ impl Wallet {
return Err(WalletError::Other(format!(
"not enough nonces: need {} signers, have {}",
account.threshold,
pending
.input_nonces
.first()
.map_or(0, |n| n.len())
pending.input_nonces.first().map_or(0, |n| n.len())
)));
}
@@ -1213,10 +1210,8 @@ impl Wallet {
// Proposer: add key_offset to weighted share; co-signer: bare share.
let privkey_hex = if is_proposer && i < pending.input_key_offsets.len() {
let offset_bytes =
hex::decode(&pending.input_key_offsets[i]).map_err(|e| {
WalletError::Other(format!("bad key offset hex: {}", e))
})?;
let offset_bytes = hex::decode(&pending.input_key_offsets[i])
.map_err(|e| WalletError::Other(format!("bad key offset hex: {}", e)))?;
let mut offset = [0u8; 32];
offset[..offset_bytes.len().min(32)]
.copy_from_slice(&offset_bytes[..offset_bytes.len().min(32)]);