Skip to content

Commit 946fde6

Browse files
committed
Fix sphincs signing in ckb-sphincs-tools
1 parent 4fec432 commit 946fde6

File tree

1 file changed

+59
-20
lines changed

1 file changed

+59
-20
lines changed

tools/ckb-sphincs-tools/src/sub_conversion.rs

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use ckb_hash::blake2b_256;
44
use ckb_jsonrpc_types as json_types;
55
use ckb_jsonrpc_types::Either;
66
use ckb_sdk::rpc::CkbRpcClient;
7-
use ckb_sphincs_utils::SphincsPlus;
7+
use ckb_sphincs_utils::sphincsplus::*;
88
use ckb_types::{
99
bytes::Bytes,
1010
core::{Capacity, DepType, ScriptHashType, TransactionBuilder, TransactionView},
@@ -126,13 +126,18 @@ pub fn sign_tx_by_input_group(
126126
.build()
127127
}
128128

129-
pub fn sign_tx_sphincs_plus(tx: TransactionView, key: &SphincsPlus) -> TransactionView {
129+
pub fn sign_tx_sphincs_plus(
130+
tx: TransactionView,
131+
inputs: &[(CellOutput, Bytes)],
132+
key: &SphincsPlus,
133+
) -> TransactionView {
130134
let witnesses_len = tx.witnesses().len();
131-
sign_tx_by_input_group_sphincs_plus(tx, key, 0, witnesses_len)
135+
sign_tx_by_input_group_sphincs_plus(tx, inputs, key, 0, witnesses_len)
132136
}
133137

134138
pub fn sign_tx_by_input_group_sphincs_plus(
135139
tx: TransactionView,
140+
inputs: &[(CellOutput, Bytes)],
136141
key: &SphincsPlus,
137142
begin_index: usize,
138143
len: usize,
@@ -144,21 +149,35 @@ pub fn sign_tx_by_input_group_sphincs_plus(
144149
.enumerate()
145150
.map(|(i, _)| {
146151
if i == begin_index {
147-
let mut blake2b = ckb_hash::new_blake2b();
152+
let mut blake2b = ckb_hash::Blake2bBuilder::new(32)
153+
.personal(b"ckb-sphincs+-msg")
154+
.build();
148155
let mut message = [0u8; 32];
156+
// CKB_TX_MESSAGE_ALL process, see: https://github.com/nervosnetwork/rfcs/pull/446
149157
blake2b.update(&tx_hash.raw_data());
158+
// digest input cells
159+
for (cell_output, cell_data) in inputs {
160+
blake2b.update(cell_output.as_slice());
161+
162+
blake2b.update(&(cell_data.len() as u32).to_le_bytes());
163+
blake2b.update(cell_data);
164+
}
150165
// digest the first witness
151166
let witness = WitnessArgs::new_unchecked(tx.witnesses().get(i).unwrap().unpack());
152-
let zero_lock: Bytes = vec![0; key.get_sign_len() + key.get_pk_len()].into();
167+
let zero_lock: Bytes = vec![0; 5 + key.get_sign_len() + key.get_pk_len()].into();
153168

154169
let witness_for_digest = witness
155170
.clone()
156171
.as_builder()
157172
.lock(Some(zero_lock).pack())
158173
.build();
159-
let witness_len = witness_for_digest.as_bytes().len() as u64;
160-
blake2b.update(&witness_len.to_le_bytes());
161-
blake2b.update(&witness_for_digest.as_bytes());
174+
175+
// digest the first witness
176+
blake2b.update(&witness_for_digest.as_slice()[0..16]);
177+
blake2b.update(witness_for_digest.input_type().as_slice());
178+
blake2b.update(witness_for_digest.output_type().as_slice());
179+
180+
// digest the remaining witnesses
162181
((i + 1)..(i + len)).for_each(|n| {
163182
let witness = tx.witnesses().get(n).unwrap();
164183
let witness_len = witness.raw_data().len() as u64;
@@ -169,10 +188,11 @@ pub fn sign_tx_by_input_group_sphincs_plus(
169188
let message = H256::from(message);
170189

171190
let witness_data = {
172-
let mut data = vec![0; key.get_sign_len() + key.get_pk_len()];
191+
let mut data = vec![0; 5 + key.get_sign_len() + key.get_pk_len()];
173192

174-
data[..key.get_sign_len()].copy_from_slice(&key.sign(message.as_bytes()));
175-
data[key.get_sign_len()..].copy_from_slice(&key.pk);
193+
data[0..5].copy_from_slice(&single_sign_witness_prefix().unwrap());
194+
data[5..key.get_sign_len() + 5].copy_from_slice(&key.pk);
195+
data[key.get_sign_len() + 5..].copy_from_slice(&key.sign(message.as_bytes()));
176196

177197
Bytes::from(data)
178198
};
@@ -253,8 +273,18 @@ pub fn cc_to_sphincsplus(
253273
.witness(witness_args.as_bytes().pack());
254274

255275
// output cell
276+
let sphincs_args: Bytes = {
277+
let mut hasher = ckb_hash::Blake2bBuilder::new(32)
278+
.personal(b"ckb-sphincs+-sct")
279+
.build();
280+
hasher.update(&single_sign_script_args_prefix().expect("prefix"));
281+
hasher.update(&key.pk);
282+
let mut result = [0u8; 32];
283+
hasher.finalize(&mut result);
284+
result.to_vec().into()
285+
};
256286
let output_script = Script::new_builder()
257-
.args(Bytes::from(blake2b_256(&key.pk).to_vec()).pack())
287+
.args(sphincs_args.pack())
258288
.code_hash(Byte32::from_slice(&get_sphincsplus_code_hash()).unwrap())
259289
.hash_type(ScriptHashType::Data1.into())
260290
.build();
@@ -310,15 +340,24 @@ pub fn cc_to_def_lock_script(
310340
.transaction
311341
.expect("input transaction is empty");
312342

313-
let input_cell = {
343+
let (input_cell, input_cell_data) = {
314344
let tx = input_tx.inner;
315345
match tx {
316-
Either::Left(tx_view) => tx_view
317-
.inner
318-
.outputs
319-
.get(tx_index as usize)
320-
.expect("input index invade")
321-
.clone(),
346+
Either::Left(tx_view) => (
347+
tx_view
348+
.inner
349+
.outputs
350+
.get(tx_index as usize)
351+
.expect("input index invade")
352+
.clone(),
353+
tx_view
354+
.inner
355+
.outputs_data
356+
.get(tx_index as usize)
357+
.expect("input index invade")
358+
.clone()
359+
.into_bytes(),
360+
),
322361
Either::Right(_json_byte) => {
323362
panic!("unsupport")
324363
}
@@ -383,7 +422,7 @@ pub fn cc_to_def_lock_script(
383422
.output_data(Bytes::new().pack());
384423

385424
let tx = tx_builder.build();
386-
let tx = sign_tx_sphincs_plus(tx, &key);
425+
let tx = sign_tx_sphincs_plus(tx, &[(input_cell.into(), input_cell_data)], &key);
387426

388427
println!("tx hash: {:?}", tx.hash());
389428
let outputs_validator = Some(json_types::OutputsValidator::Passthrough);

0 commit comments

Comments
 (0)