neo3/neo_builder/transaction/
witness.rs1use crate::{
2 builder::{BuilderError, InvocationScript, ScriptBuilder, VerificationScript},
3 codec::{Decoder, Encoder, NeoSerializable},
4 crypto::{KeyPair, Secp256r1PublicKey, Secp256r1Signature},
5 Bytes, ContractParameter,
6};
7use serde::{Deserialize, Serialize};
8
9#[derive(Hash, Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
10pub struct Witness {
11 pub invocation: InvocationScript,
12 pub verification: VerificationScript,
13}
14
15impl Witness {
16 pub fn new() -> Self {
17 Self { invocation: InvocationScript::new(), verification: VerificationScript::new() }
18 }
19
20 pub fn from_scripts(invocation_script: Bytes, verification_script: Bytes) -> Self {
21 Self {
22 invocation: InvocationScript::new_with_script(invocation_script),
23 verification: VerificationScript::from(verification_script),
24 }
25 }
26
27 pub fn from_scripts_obj(
28 invocation_script: InvocationScript,
29 verification_script: VerificationScript,
30 ) -> Self {
31 Self { invocation: invocation_script, verification: verification_script }
32 }
33
34 pub fn create(message_to_sign: Bytes, key_pair: &KeyPair) -> Result<Self, BuilderError> {
35 let invocation_script =
36 InvocationScript::from_message_and_key_pair(message_to_sign, key_pair).unwrap();
37 let verification_script = VerificationScript::from_public_key(&key_pair.public_key());
38 Ok(Self { invocation: invocation_script, verification: verification_script })
39 }
40
41 pub fn create_multi_sig_witness(
42 signing_threshold: u8,
43 signatures: Vec<Secp256r1Signature>,
44 mut public_keys: Vec<Secp256r1PublicKey>,
45 ) -> Result<Self, BuilderError> {
46 let verification_script =
47 VerificationScript::from_multi_sig(public_keys.as_mut_slice(), signing_threshold);
48 Self::create_multi_sig_witness_script(signatures, verification_script)
49 }
50
51 pub fn create_multi_sig_witness_script(
52 signatures: Vec<Secp256r1Signature>,
53 verification_script: VerificationScript,
54 ) -> Result<Self, BuilderError> {
55 let threshold = verification_script.get_signing_threshold().unwrap();
56 if signatures.len() < threshold {
57 return Err(BuilderError::SignerConfiguration(
58 "Not enough signatures provided for the required signing threshold.".to_string(),
59 ));
60 }
61
62 let invocation_script =
63 InvocationScript::from_signatures(&signatures[..threshold as usize]);
64 Ok(Self { invocation: invocation_script, verification: verification_script })
65 }
66
67 pub fn create_contract_witness(params: Vec<ContractParameter>) -> Result<Self, BuilderError> {
68 if params.is_empty() {
69 return Ok(Self::new());
70 }
71
72 let mut builder = ScriptBuilder::new();
73 for param in params {
74 builder.push_param(¶m).map_err(|e| {
75 BuilderError::IllegalArgument(format!("Failed to push parameter: {}", e))
76 })?;
77 }
78 let invocation_script = builder.to_bytes();
79
80 Ok(Self {
81 invocation: InvocationScript::new_with_script(invocation_script),
82 verification: VerificationScript::new(),
83 })
84 }
85}
86
87impl NeoSerializable for Witness {
88 type Error = BuilderError;
89
90 fn size(&self) -> usize {
91 self.invocation.size() + self.verification.size()
92 }
93
94 fn encode(&self, writer: &mut Encoder) {
95 self.invocation.encode(writer);
96 self.verification.encode(writer);
97 }
98
99 fn decode(reader: &mut Decoder) -> Result<Self, Self::Error> {
100 let invocation = InvocationScript::decode(reader)?;
101 let verification = VerificationScript::decode(reader)?;
102 Ok(Self { invocation, verification })
103 }
104 fn to_array(&self) -> Vec<u8> {
105 let mut writer = Encoder::new();
106 self.encode(&mut writer);
107 writer.to_bytes()
108 }
109}