bitcoin/blockdata/script/
builder.rs1use core::fmt;
4
5use secp256k1::XOnlyPublicKey;
6
7use crate::blockdata::locktime::absolute;
8use crate::blockdata::opcodes::all::*;
9use crate::blockdata::opcodes::{self, Opcode};
10use crate::blockdata::script::{opcode_to_verify, write_scriptint, PushBytes, Script, ScriptBuf};
11use crate::blockdata::transaction::Sequence;
12use crate::key::PublicKey;
13use crate::prelude::*;
14
15#[derive(PartialEq, Eq, Clone)]
17pub struct Builder(ScriptBuf, Option<Opcode>);
18
19impl Builder {
20 #[inline]
22 pub const fn new() -> Self { Builder(ScriptBuf::new(), None) }
23
24 pub fn len(&self) -> usize { self.0.len() }
26
27 pub fn is_empty(&self) -> bool { self.0.is_empty() }
29
30 pub fn push_int(self, data: i64) -> Builder {
35 if data == -1 || (1..=16).contains(&data) {
37 let opcode = Opcode::from((data - 1 + opcodes::OP_TRUE.to_u8() as i64) as u8);
38 self.push_opcode(opcode)
39 }
40 else if data == 0 {
42 self.push_opcode(opcodes::OP_0)
43 }
44 else {
46 self.push_int_non_minimal(data)
47 }
48 }
49
50 pub(in crate::blockdata) fn push_int_non_minimal(self, data: i64) -> Builder {
54 let mut buf = [0u8; 8];
55 let len = write_scriptint(&mut buf, data);
56 self.push_slice(&<&PushBytes>::from(&buf)[..len])
57 }
58
59 pub fn push_slice<T: AsRef<PushBytes>>(mut self, data: T) -> Builder {
61 self.0.push_slice(data);
62 self.1 = None;
63 self
64 }
65
66 pub fn push_key(self, key: &PublicKey) -> Builder {
68 if key.compressed {
69 self.push_slice(key.inner.serialize())
70 } else {
71 self.push_slice(key.inner.serialize_uncompressed())
72 }
73 }
74
75 pub fn push_x_only_key(self, x_only_key: &XOnlyPublicKey) -> Builder {
77 self.push_slice(x_only_key.serialize())
78 }
79
80 pub fn push_opcode(mut self, data: Opcode) -> Builder {
82 self.0.push_opcode(data);
83 self.1 = Some(data);
84 self
85 }
86
87 pub fn push_verify(mut self) -> Builder {
98 match opcode_to_verify(self.1) {
100 Some(opcode) => {
101 (self.0).0.pop();
102 self.push_opcode(opcode)
103 }
104 None => self.push_opcode(OP_VERIFY),
105 }
106 }
107
108 pub fn push_lock_time(self, lock_time: absolute::LockTime) -> Builder {
110 self.push_int(lock_time.to_consensus_u32().into())
111 }
112
113 pub fn push_sequence(self, sequence: Sequence) -> Builder {
115 self.push_int(sequence.to_consensus_u32().into())
116 }
117
118 pub fn into_script(self) -> ScriptBuf { self.0 }
120
121 pub fn into_bytes(self) -> Vec<u8> { self.0.into() }
123
124 pub fn as_script(&self) -> &Script { &self.0 }
126
127 pub fn as_bytes(&self) -> &[u8] { self.0.as_bytes() }
129}
130
131impl Default for Builder {
132 fn default() -> Builder { Builder::new() }
133}
134
135impl From<Vec<u8>> for Builder {
137 fn from(v: Vec<u8>) -> Builder {
138 let script = ScriptBuf::from(v);
139 let last_op = script.last_opcode();
140 Builder(script, last_op)
141 }
142}
143
144impl fmt::Display for Builder {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt_asm(f) }
146}
147
148internals::debug_from_display!(Builder);