bitcoin/script: inline bitcoin varint encoding
What changed, and why it matters
This is a small code cleanup change. It removes a local helper function that wrapped rust-bitcoin's variable-length integer serializer, and instead calls rust-bitcoin's serializer directly at each place it is used. The actual bytes produced are identical, so this does not change behavior or fix a security issue.
No security action required. Treat as a normal refactoring review; verify CI/tests still pass and that the rust-bitcoin version's VarInt encoding remains compatible.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit deletes src/rust/bitbox02-rust/src/hww/api/bitcoin/script.rs, which contained a serialize_varint() helper that simply delegated to bitcoin::consensus::encode::serialize(&VarInt(…)). All call sites are updated to use bitcoin::consensus::encode::{VarInt, serialize} directly. The diff shows one-to-one replacements with no logic changes, no boundary/encoding changes, and no new dependencies. The removed module also contained unit tests that verified the varint encoding matched btcd’s wire.WriteVarInt; those tests are removed along with the wrapper.
Changed components
src/rust/bitbox02-rust/src/hww/api/bitcoin/bip143.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/payment_request.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/signmsg.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rsInspect captured patch +16 / −86
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin.rs
index a2057a2..dfdbcda 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin.rs
@@ -13,7 +13,6 @@ pub mod params;
mod payment_request;
mod policies;
mod registration;
-mod script;
mod script_configs;
pub mod signmsg;
pub mod signtx;
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/bip143.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/bip143.rs
index 84aa91f..459f43f 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/bip143.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/bip143.rs
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: Apache-2.0
+use bitcoin::consensus::encode::{VarInt, serialize};
use sha2::Digest;
use sha2::Sha256;
-use super::script::serialize_varint;
-
/// https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification
pub struct Args<'a> {
pub version: u32,
@@ -36,7 +35,7 @@ pub fn sighash(args: &Args) -> [u8; 32] {
ctx.update(args.outpoint_hash);
ctx.update(args.outpoint_index.to_le_bytes());
// 5.
- ctx.update(serialize_varint(args.sighash_script.len() as u64));
+ ctx.update(serialize(&VarInt(args.sighash_script.len() as u64)));
ctx.update(args.sighash_script);
// 6.
ctx.update(args.prevout_value.to_le_bytes());
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/payment_request.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/payment_request.rs
index 51bacb1..2110385 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/payment_request.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/payment_request.rs
@@ -8,7 +8,6 @@ use alloc::vec::Vec;
use super::common::format_amount;
use super::params;
-use super::script::serialize_varint;
use pb::btc_payment_request_request::{Memo, memo};
use pb::btc_sign_init_request::FormatUnit;
@@ -20,6 +19,7 @@ use crate::workflow::verify_message;
use hex_lit::hex;
use sha2::{Digest, Sha256};
+use bitcoin::consensus::encode::{VarInt, serialize};
use bitcoin::secp256k1;
// Arbitrary limit on number of memos that a payment request can show to the user.
@@ -227,7 +227,7 @@ pub enum ValidationError {
}
fn hash_data_lenprefixed<U: digest::Update>(hasher: &mut U, data: &[u8]) {
- hasher.update(&serialize_varint(data.len() as u64));
+ hasher.update(&serialize(&VarInt(data.len() as u64)));
hasher.update(data);
}
@@ -249,7 +249,7 @@ fn compute_sighash(
// recipientName
hash_data_lenprefixed(&mut sighash, payment_request.recipient_name.as_bytes());
// memos
- sighash.update(serialize_varint(payment_request.memos.len() as u64));
+ sighash.update(serialize(&VarInt(payment_request.memos.len() as u64)));
for memo in payment_request.memos.iter() {
match memo {
Memo {
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/script.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/script.rs
deleted file mode 100644
index 8c5389f..0000000
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/script.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-use alloc::vec::Vec;
-
-/// Serialize a number in the VarInt encoding.
-/// https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
-pub fn serialize_varint(value: u64) -> Vec<u8> {
- bitcoin::consensus::encode::serialize(&bitcoin::consensus::encode::VarInt(value))
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_serialize_varint() {
- // Go script to generate the test vectors below.
- /*
- package main
-
- import (
- "bytes"
- "encoding/hex"
- "fmt"
- "regexp"
-
- "github.com/btcsuite/btcd/wire"
- )
-
- func main() {
- formatHex := func(v []byte) string {
- h := hex.EncodeToString(v)
- return regexp.MustCompile("(..)").ReplaceAllString(h, "\\x$1")
- }
- for _, val := range []uint64{0, 1, 2, 127, 128, 255, 256, 257, 300, 0xFFFF - 1, 0xFFFF, 0xFFFF + 1, 0xFFFF + 100, 0xFFFFFFFF - 1, 0xFFFFFFFF, 0xFFFFFFFF + 1, 0xFFFFFFFF + 100, 0XFFFFFFFFFFFFFFFF} {
- buf := new(bytes.Buffer)
- wire.WriteVarInt(buf, 0, val)
- fmt.Printf("assert_eq!(serialize_varint(0x%x), b\"%s\");\n", val, formatHex(buf.Bytes()))
- }
- }
- */
-
- assert_eq!(serialize_varint(0x0), b"\x00");
- assert_eq!(serialize_varint(0x1), b"\x01");
- assert_eq!(serialize_varint(0x2), b"\x02");
- assert_eq!(serialize_varint(0x7f), b"\x7f");
- assert_eq!(serialize_varint(0x80), b"\x80");
- assert_eq!(serialize_varint(0xff), b"\xfd\xff\x00");
- assert_eq!(serialize_varint(0x100), b"\xfd\x00\x01");
- assert_eq!(serialize_varint(0x101), b"\xfd\x01\x01");
- assert_eq!(serialize_varint(0x12c), b"\xfd\x2c\x01");
- assert_eq!(serialize_varint(0xfffe), b"\xfd\xfe\xff");
- assert_eq!(serialize_varint(0xffff), b"\xfd\xff\xff");
- assert_eq!(serialize_varint(0x10000), b"\xfe\x00\x00\x01\x00");
- assert_eq!(serialize_varint(0x10063), b"\xfe\x63\x00\x01\x00");
- assert_eq!(serialize_varint(0xfffffffe), b"\xfe\xfe\xff\xff\xff");
- assert_eq!(serialize_varint(0xffffffff), b"\xfe\xff\xff\xff\xff");
- assert_eq!(
- serialize_varint(0x100000000),
- b"\xff\x00\x00\x00\x00\x01\x00\x00\x00"
- );
- assert_eq!(
- serialize_varint(0x100000063),
- b"\xff\x63\x00\x00\x00\x01\x00\x00\x00"
- );
- assert_eq!(
- serialize_varint(0xffffffffffffffff),
- b"\xff\xff\xff\xff\xff\xff\xff\xff\xff"
- );
- }
-}
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signmsg.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signmsg.rs
index b717e3d..2b85a8c 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signmsg.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signmsg.rs
@@ -17,6 +17,7 @@ use crate::keystore;
use crate::hal::Ui;
use crate::workflow::verify_message;
+use bitcoin::consensus::encode::{VarInt, serialize};
const MAX_MESSAGE_SIZE: usize = 1024;
@@ -79,7 +80,7 @@ pub async fn process(
// Electrum re-used it for p2wpkh-p2sh and p2wpkh addresses.
let mut msg: Vec<u8> = Vec::new();
msg.extend(b"\x18Bitcoin Signed Message:\n");
- msg.extend(super::script::serialize_varint(request.msg.len() as _));
+ msg.extend(serialize(&VarInt(request.msg.len() as _)));
msg.extend(&request.msg);
let sighash: [u8; 32] = Sha256::digest(Sha256::digest(msg)).into();
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
index 38e6c58..3aca136 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
@@ -7,7 +7,6 @@ use crate::hal::ui::{ConfirmParams, Progress};
use super::common::format_amount;
use super::payment_request;
use super::policies::TaprootSpendInfo;
-use super::script::serialize_varint;
use super::script_configs::{ValidatedScriptConfig, ValidatedScriptConfigWithKeypath};
use super::{bip143, bip341, common, keypath};
@@ -27,6 +26,7 @@ use pb::btc_sign_init_request::FormatUnit;
use pb::btc_sign_next_response::Type as NextType;
use sha2::{Digest, Sha256};
+use bitcoin::consensus::encode::{VarInt, serialize};
use bitcoin::hashes::Hash;
use bitcoin::key::TapTweak;
@@ -359,7 +359,7 @@ async fn handle_prevtx(
let mut hasher = Sha256::new();
hasher.update(prevtx_init.version.to_le_bytes());
- hasher.update(serialize_varint(prevtx_init.num_inputs as u64).as_slice());
+ hasher.update(serialize(&VarInt(prevtx_init.num_inputs as u64)));
for prevtx_input_index in 0..prevtx_init.num_inputs {
// Update progress.
progress_component.set({
@@ -372,12 +372,14 @@ async fn handle_prevtx(
let prevtx_input = get_prevtx_input(input_index, prevtx_input_index, next_response).await?;
hasher.update(prevtx_input.prev_out_hash.as_slice());
hasher.update(prevtx_input.prev_out_index.to_le_bytes());
- hasher.update(serialize_varint(prevtx_input.signature_script.len() as u64).as_slice());
+ hasher.update(serialize(&VarInt(
+ prevtx_input.signature_script.len() as u64
+ )));
hasher.update(prevtx_input.signature_script.as_slice());
hasher.update(prevtx_input.sequence.to_le_bytes());
}
- hasher.update(serialize_varint(prevtx_init.num_outputs as u64).as_slice());
+ hasher.update(serialize(&VarInt(prevtx_init.num_outputs as u64)));
for prevtx_output_index in 0..prevtx_init.num_outputs {
// Update progress.
progress_component.set({
@@ -395,7 +397,7 @@ async fn handle_prevtx(
return Err(Error::InvalidInput);
}
hasher.update(prevtx_output.value.to_le_bytes());
- hasher.update(serialize_varint(prevtx_output.pubkey_script.len() as u64).as_slice());
+ hasher.update(serialize(&VarInt(prevtx_output.pubkey_script.len() as u64)));
hasher.update(prevtx_output.pubkey_script.as_slice());
}
@@ -799,7 +801,7 @@ async fn _process(
script_config_account,
)?
.pk_script(coin_params)?;
- hasher_scriptpubkeys.update(serialize_varint(pk_script.len() as u64).as_slice());
+ hasher_scriptpubkeys.update(serialize(&VarInt(pk_script.len() as u64)));
hasher_scriptpubkeys.update(pk_script.as_slice());
if !taproot_only {
@@ -1083,7 +1085,7 @@ async fn _process(
// only SIGHASH_ALL supported.
hasher_outputs.update(tx_output.value.to_le_bytes());
let pk_script = payload.pk_script(coin_params)?;
- hasher_outputs.update(serialize_varint(pk_script.len() as u64).as_slice());
+ hasher_outputs.update(serialize(&VarInt(pk_script.len() as u64)));
hasher_outputs.update(pk_script.as_slice());
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.