neo3/neo_builder/transaction/
witness.rs

1use 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(&param).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}