● 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:
@@ -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"
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)]);
|
||||
|
||||
Reference in New Issue
Block a user