Skip to content

Commit 4b16e47

Browse files
committed
feat(stack): encode signatures as concatenated bytes
1 parent 3df70a9 commit 4b16e47

File tree

2 files changed

+71
-47
lines changed

2 files changed

+71
-47
lines changed

stack/src/operators.rs

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@ use crate::{ScriptContext, ScriptError};
22
use scriptful::prelude::{ConditionStack, Stack};
33
use serde::{Deserialize, Serialize};
44
use witnet_crypto::hash::{calculate_sha256, Sha256};
5-
use witnet_data_structures::chain::Hash;
6-
use witnet_data_structures::{
7-
chain::{KeyedSignature, PublicKeyHash},
8-
proto::ProtobufConvert,
9-
};
5+
use witnet_data_structures::chain::{Hash, PublicKey, Secp256k1Signature, Signature};
6+
use witnet_data_structures::chain::{KeyedSignature, PublicKeyHash};
107

118
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
129
// TODO: Include more operators
@@ -33,7 +30,7 @@ pub enum MyOperator {
3330
EndIf,
3431
}
3532

36-
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
33+
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
3734
pub enum MyValue {
3835
/// A binary value: either `true` or `false`.
3936
Boolean(bool),
@@ -43,6 +40,43 @@ pub enum MyValue {
4340
Bytes(Vec<u8>),
4441
}
4542

43+
impl MyValue {
44+
pub fn from_signature(ks: &KeyedSignature) -> Self {
45+
let public_key_bytes = ks.public_key.to_bytes();
46+
let signature_bytes = match &ks.signature {
47+
Signature::Secp256k1(signature) => &signature.der,
48+
};
49+
50+
let bytes = [&public_key_bytes[..], signature_bytes].concat();
51+
52+
MyValue::Bytes(bytes)
53+
}
54+
55+
pub fn to_signature(&self) -> Result<KeyedSignature, ScriptError> {
56+
match self {
57+
MyValue::Bytes(bytes) => {
58+
// Public keys are always 33 bytes, so first 33 bytes of KeyedSignature will always
59+
// be the public key, and the rest will be the signature
60+
if bytes.len() < 33 {
61+
return Err(ScriptError::InvalidSignature);
62+
}
63+
let (public_key_bytes, signature_bytes) = bytes.split_at(33);
64+
65+
let ks = KeyedSignature {
66+
public_key: PublicKey::try_from_slice(public_key_bytes)
67+
.expect("public_key_bytes must have length 33"),
68+
signature: Signature::Secp256k1(Secp256k1Signature {
69+
der: signature_bytes.to_vec(),
70+
}),
71+
};
72+
73+
Ok(ks)
74+
}
75+
_ => Err(ScriptError::UnexpectedArgument),
76+
}
77+
}
78+
}
79+
4680
fn equal_operator(stack: &mut Stack<MyValue>) -> Result<(), ScriptError> {
4781
let a = stack.pop().ok_or(ScriptError::EmptyStackPop)?;
4882
let b = stack.pop().ok_or(ScriptError::EmptyStackPop)?;
@@ -146,30 +180,21 @@ fn check_multi_sig(
146180
) -> Result<bool, ScriptError> {
147181
let mut signed_pkhs = vec![];
148182
let mut keyed_signatures = vec![];
149-
for signature in bytes_keyed_signatures {
150-
match signature {
151-
MyValue::Bytes(bytes) => {
152-
// TODO: signatures are encoded using Protocol Buffers, maybe choose a different encoding?
153-
let ks: KeyedSignature = KeyedSignature::from_pb_bytes(&bytes)
154-
.map_err(|_e| ScriptError::InvalidSignature)?;
155-
let signed_pkh = ks.public_key.pkh();
156-
signed_pkhs.push(signed_pkh);
157-
let signature = ks
158-
.signature
159-
.clone()
160-
.try_into()
161-
.map_err(|_e| ScriptError::InvalidSignature)?;
162-
let public_key = ks
163-
.public_key
164-
.clone()
165-
.try_into()
166-
.map_err(|_e| ScriptError::InvalidPublicKey)?;
167-
keyed_signatures.push((signature, public_key));
168-
}
169-
_ => {
170-
return Err(ScriptError::UnexpectedArgument);
171-
}
172-
}
183+
for value in bytes_keyed_signatures {
184+
let ks = value.to_signature()?;
185+
let signed_pkh = ks.public_key.pkh();
186+
signed_pkhs.push(signed_pkh);
187+
let signature = ks
188+
.signature
189+
.clone()
190+
.try_into()
191+
.map_err(|_e| ScriptError::InvalidSignature)?;
192+
let public_key = ks
193+
.public_key
194+
.clone()
195+
.try_into()
196+
.map_err(|_e| ScriptError::InvalidPublicKey)?;
197+
keyed_signatures.push((signature, public_key));
173198
}
174199

175200
let mut pkhs = vec![];

stack/src/tests.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::{
44
};
55
use witnet_crypto::hash::calculate_sha256;
66
use witnet_data_structures::chain::KeyedSignature;
7-
use witnet_data_structures::proto::ProtobufConvert;
87

98
const EQUAL_OPERATOR_HASH: [u8; 20] = [
109
52, 128, 191, 80, 253, 28, 169, 253, 237, 29, 0, 51, 201, 0, 31, 203, 157, 99, 218, 210,
@@ -161,7 +160,7 @@ fn test_check_sig() {
161160

162161
let pk_1 = ks_1.public_key.clone();
163162

164-
let witness = vec![Item::Value(MyValue::Bytes(ks_1.to_pb_bytes().unwrap()))];
163+
let witness = vec![Item::Value(MyValue::from_signature(&ks_1))];
165164
let redeem_bytes = encode(&[
166165
Item::Value(MyValue::Bytes(pk_1.pkh().bytes().to_vec())),
167166
Item::Operator(MyOperator::CheckSig),
@@ -176,7 +175,7 @@ fn test_check_sig() {
176175
Ok(true)
177176
));
178177

179-
let invalid_witness = vec![Item::Value(MyValue::Bytes(ks_2.to_pb_bytes().unwrap()))];
178+
let invalid_witness = vec![Item::Value(MyValue::from_signature(&ks_2))];
180179
assert!(matches!(
181180
execute_redeem_script(
182181
&encode(&invalid_witness).unwrap(),
@@ -198,8 +197,8 @@ fn test_check_multisig() {
198197
let pk_3 = ks_3.public_key.clone();
199198

200199
let witness = vec![
201-
Item::Value(MyValue::Bytes(ks_1.to_pb_bytes().unwrap())),
202-
Item::Value(MyValue::Bytes(ks_2.to_pb_bytes().unwrap())),
200+
Item::Value(MyValue::from_signature(&ks_1)),
201+
Item::Value(MyValue::from_signature(&ks_2)),
203202
];
204203
let redeem_bytes = encode(&[
205204
Item::Value(MyValue::Integer(2)),
@@ -220,8 +219,8 @@ fn test_check_multisig() {
220219
));
221220

222221
let other_valid_witness = vec![
223-
Item::Value(MyValue::Bytes(ks_1.to_pb_bytes().unwrap())),
224-
Item::Value(MyValue::Bytes(ks_3.to_pb_bytes().unwrap())),
222+
Item::Value(MyValue::from_signature(&ks_1)),
223+
Item::Value(MyValue::from_signature(&ks_3)),
225224
];
226225
assert!(matches!(
227226
execute_redeem_script(
@@ -234,8 +233,8 @@ fn test_check_multisig() {
234233

235234
let ks_4 = test_ks_id(4);
236235
let invalid_witness = vec![
237-
Item::Value(MyValue::Bytes(ks_1.to_pb_bytes().unwrap())),
238-
Item::Value(MyValue::Bytes(ks_4.to_pb_bytes().unwrap())),
236+
Item::Value(MyValue::from_signature(&ks_1)),
237+
Item::Value(MyValue::from_signature(&ks_4)),
239238
];
240239
assert!(matches!(
241240
execute_redeem_script(
@@ -416,7 +415,7 @@ fn test_execute_script_atomic_swap() {
416415

417416
// 1 can spend after timelock
418417
let witness_script = vec![
419-
Item::Value(MyValue::Bytes(ks_1.to_pb_bytes().unwrap())),
418+
Item::Value(MyValue::from_signature(&ks_1)),
420419
Item::Value(MyValue::Boolean(true)),
421420
];
422421
assert!(matches!(
@@ -433,7 +432,7 @@ fn test_execute_script_atomic_swap() {
433432

434433
// 1 cannot spend before timelock
435434
let witness_script = vec![
436-
Item::Value(MyValue::Bytes(ks_1.to_pb_bytes().unwrap())),
435+
Item::Value(MyValue::from_signature(&ks_1)),
437436
Item::Value(MyValue::Boolean(true)),
438437
];
439438
assert!(matches!(
@@ -450,7 +449,7 @@ fn test_execute_script_atomic_swap() {
450449

451450
// 2 can spend with secret
452451
let witness_script = vec![
453-
Item::Value(MyValue::Bytes(ks_2.to_pb_bytes().unwrap())),
452+
Item::Value(MyValue::from_signature(&ks_2)),
454453
Item::Value(MyValue::Bytes(secret)),
455454
Item::Value(MyValue::Boolean(false)),
456455
];
@@ -468,7 +467,7 @@ fn test_execute_script_atomic_swap() {
468467

469468
// 2 cannot spend with a wrong secret
470469
let witness_script = vec![
471-
Item::Value(MyValue::Bytes(ks_2.to_pb_bytes().unwrap())),
470+
Item::Value(MyValue::from_signature(&ks_2)),
472471
Item::Value(MyValue::Bytes(vec![0, 0, 0, 0])),
473472
Item::Value(MyValue::Boolean(false)),
474473
];
@@ -512,7 +511,7 @@ fn test_execute_script_atomic_swap_2() {
512511
.unwrap();
513512

514513
// 1 can spend after timelock
515-
let witness_script = vec![Item::Value(MyValue::Bytes(ks_1.to_pb_bytes().unwrap()))];
514+
let witness_script = vec![Item::Value(MyValue::from_signature(&ks_1))];
516515
assert!(matches!(
517516
execute_redeem_script(
518517
&encode(&witness_script).unwrap(),
@@ -539,7 +538,7 @@ fn test_execute_script_atomic_swap_2() {
539538

540539
// 2 can spend with secret
541540
let witness_script = vec![
542-
Item::Value(MyValue::Bytes(ks_2.to_pb_bytes().unwrap())),
541+
Item::Value(MyValue::from_signature(&ks_2)),
543542
Item::Value(MyValue::Bytes(secret.clone())),
544543
];
545544
assert!(matches!(
@@ -556,7 +555,7 @@ fn test_execute_script_atomic_swap_2() {
556555

557556
// 2 cannot spend with a wrong secret
558557
let witness_script = vec![
559-
Item::Value(MyValue::Bytes(ks_2.to_pb_bytes().unwrap())),
558+
Item::Value(MyValue::from_signature(&ks_2)),
560559
Item::Value(MyValue::Bytes(vec![0, 0, 0, 0])),
561560
];
562561
assert!(matches!(
@@ -573,7 +572,7 @@ fn test_execute_script_atomic_swap_2() {
573572

574573
// 2 cannot spend after timelock
575574
let witness_script = vec![
576-
Item::Value(MyValue::Bytes(ks_2.to_pb_bytes().unwrap())),
575+
Item::Value(MyValue::from_signature(&ks_2)),
577576
Item::Value(MyValue::Bytes(secret)),
578577
];
579578
assert!(matches!(

0 commit comments

Comments
 (0)