1use serde::{Deserialize, Serialize};
4
5#[cfg(feature = "production")]
6use rustc_hash::FxHashMap;
7#[cfg(feature = "production")]
8use smallvec::SmallVec;
9#[cfg(not(feature = "production"))]
10use std::collections::HashMap;
11
12#[cfg(feature = "production")]
14pub use smallvec;
15
16#[cfg(feature = "production")]
18#[macro_export]
19macro_rules! tx_inputs {
20 ($($item:expr),* $(,)?) => {
21 {
22 $crate::smallvec::SmallVec::from_vec(vec![$($item),*])
23 }
24 };
25}
26
27#[cfg(not(feature = "production"))]
28#[macro_export]
29macro_rules! tx_inputs {
30 ($($item:expr),* $(,)?) => {
31 vec![$($item),*]
32 };
33}
34
35#[cfg(feature = "production")]
36#[macro_export]
37macro_rules! tx_outputs {
38 ($($item:expr),* $(,)?) => {
39 {
40 $crate::smallvec::SmallVec::from_vec(vec![$($item),*])
41 }
42 };
43}
44
45#[cfg(not(feature = "production"))]
46#[macro_export]
47macro_rules! tx_outputs {
48 ($($item:expr),* $(,)?) => {
49 vec![$($item),*]
50 };
51}
52
53pub type Hash = [u8; 32];
55
56pub type ByteString = Vec<u8>;
58
59pub type Witness = Vec<ByteString>;
64
65const SHARED_BYTE_INLINE_CAP: usize = 64;
67
68#[derive(Clone)]
69enum SharedRepr {
70 Inline {
71 len: u8,
72 data: [u8; SHARED_BYTE_INLINE_CAP],
73 },
74 Shared(std::sync::Arc<[u8]>),
75}
76
77#[derive(Clone)]
80pub struct SharedByteString(SharedRepr);
81
82impl std::fmt::Debug for SharedByteString {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 f.debug_tuple("SharedByteString")
85 .field(&self.as_slice())
86 .finish()
87 }
88}
89
90impl PartialEq for SharedByteString {
91 #[inline]
92 fn eq(&self, other: &Self) -> bool {
93 self.as_slice() == other.as_slice()
94 }
95}
96
97impl Eq for SharedByteString {}
98
99impl std::hash::Hash for SharedByteString {
100 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
101 self.as_slice().hash(state);
102 }
103}
104
105impl SharedByteString {
106 #[inline]
107 fn as_slice(&self) -> &[u8] {
108 match &self.0 {
109 SharedRepr::Inline { len, data } => &data[..*len as usize],
110 SharedRepr::Shared(a) => a,
111 }
112 }
113
114 #[inline]
115 fn from_bytes(v: &[u8]) -> Self {
116 if v.len() <= SHARED_BYTE_INLINE_CAP {
117 let mut data = [0u8; SHARED_BYTE_INLINE_CAP];
118 data[..v.len()].copy_from_slice(v);
119 Self(SharedRepr::Inline {
120 len: v.len() as u8,
121 data,
122 })
123 } else {
124 Self(SharedRepr::Shared(std::sync::Arc::from(v)))
125 }
126 }
127}
128
129impl std::ops::Deref for SharedByteString {
130 type Target = [u8];
131 #[inline]
132 fn deref(&self) -> &[u8] {
133 self.as_slice()
134 }
135}
136
137impl Serialize for SharedByteString {
138 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
139 self.as_slice().serialize(s)
140 }
141}
142
143impl<'de> Deserialize<'de> for SharedByteString {
144 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
145 let v: Vec<u8> = Deserialize::deserialize(d)?;
146 Ok(Self::from_bytes(&v))
147 }
148}
149
150impl From<ByteString> for SharedByteString {
151 #[inline]
152 fn from(v: ByteString) -> Self {
153 Self::from_bytes(v.as_slice())
154 }
155}
156
157impl From<&[u8]> for SharedByteString {
158 #[inline]
159 fn from(v: &[u8]) -> Self {
160 Self::from_bytes(v)
161 }
162}
163
164impl Default for SharedByteString {
165 #[inline]
166 fn default() -> Self {
167 Self(SharedRepr::Inline {
168 len: 0,
169 data: [0u8; SHARED_BYTE_INLINE_CAP],
170 })
171 }
172}
173
174impl AsRef<[u8]> for SharedByteString {
175 #[inline]
176 fn as_ref(&self) -> &[u8] {
177 self.as_slice()
178 }
179}
180
181impl SharedByteString {
182 #[inline]
184 pub fn as_arc(&self) -> std::sync::Arc<[u8]> {
185 match &self.0 {
186 SharedRepr::Shared(a) => std::sync::Arc::clone(a),
187 SharedRepr::Inline { len, data } => {
188 std::sync::Arc::from(data[..*len as usize].to_vec().into_boxed_slice())
189 }
190 }
191 }
192}
193
194pub type Natural = u64;
196
197pub type Integer = i64;
199
200#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
204pub enum Network {
205 Mainnet,
207 Testnet,
209 Regtest,
211}
212
213#[derive(Debug, Clone, Copy, PartialEq, Eq)]
218pub struct TimeContext {
219 pub network_time: u64,
222 pub median_time_past: u64,
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
234pub struct Bip54BoundaryTimestamps {
235 pub timestamp_n_minus_1: u64,
237 pub timestamp_n_minus_2015: u64,
239}
240
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
246pub enum ForkId {
247 Bip30,
249 Bip16,
251 Bip34,
253 Bip66,
255 Bip65,
257 Bip112,
259 Bip147,
261 SegWit,
263 Taproot,
265 Ctv,
267 Csfs,
269 Bip54,
271}
272
273impl Network {
274 pub fn from_env() -> Self {
281 match std::env::var("BITCOIN_NETWORK").as_deref() {
282 Ok("testnet") => Network::Testnet,
283 Ok("regtest") => Network::Regtest,
284 _ => Network::Mainnet,
285 }
286 }
287
288 pub fn hrp(&self) -> &'static str {
292 match self {
293 Network::Mainnet => "bc",
294 Network::Testnet => "tb",
295 Network::Regtest => "bcrt",
296 }
297 }
298}
299
300#[repr(transparent)]
305#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
306pub struct BlockHeight(pub u64);
307
308impl BlockHeight {
309 #[inline(always)]
311 pub fn new(height: u64) -> Self {
312 BlockHeight(height)
313 }
314
315 #[inline(always)]
317 pub fn as_u64(self) -> u64 {
318 self.0
319 }
320}
321
322impl From<u64> for BlockHeight {
323 #[inline(always)]
324 fn from(height: u64) -> Self {
325 BlockHeight(height)
326 }
327}
328
329impl From<BlockHeight> for u64 {
330 #[inline(always)]
331 fn from(height: BlockHeight) -> Self {
332 height.0
333 }
334}
335
336impl std::ops::Deref for BlockHeight {
337 type Target = u64;
338
339 #[inline(always)]
340 fn deref(&self) -> &Self::Target {
341 &self.0
342 }
343}
344
345#[repr(transparent)]
350#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
351pub struct BlockHash(pub Hash);
352
353impl BlockHash {
354 #[inline(always)]
356 pub fn new(hash: Hash) -> Self {
357 BlockHash(hash)
358 }
359
360 #[inline(always)]
362 pub fn as_hash(self) -> Hash {
363 self.0
364 }
365
366 #[inline(always)]
368 pub fn as_hash_ref(&self) -> &Hash {
369 &self.0
370 }
371}
372
373impl From<Hash> for BlockHash {
374 #[inline(always)]
375 fn from(hash: Hash) -> Self {
376 BlockHash(hash)
377 }
378}
379
380impl From<BlockHash> for Hash {
381 #[inline(always)]
382 fn from(hash: BlockHash) -> Self {
383 hash.0
384 }
385}
386
387impl std::ops::Deref for BlockHash {
388 type Target = Hash;
389
390 #[inline(always)]
391 fn deref(&self) -> &Self::Target {
392 &self.0
393 }
394}
395
396#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
400pub struct OutPoint {
401 pub hash: Hash,
402 pub index: u32,
403}
404
405#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
410pub struct TransactionInput {
411 pub prevout: OutPoint, pub sequence: Natural, pub script_sig: ByteString, }
415
416#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
418pub struct TransactionOutput {
419 pub value: Integer,
420 pub script_pubkey: ByteString,
421}
422
423#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
428pub struct Transaction {
429 pub version: Natural,
430 #[cfg(feature = "production")]
431 pub inputs: SmallVec<[TransactionInput; 2]>,
432 #[cfg(not(feature = "production"))]
433 pub inputs: Vec<TransactionInput>,
434 #[cfg(feature = "production")]
435 pub outputs: SmallVec<[TransactionOutput; 2]>,
436 #[cfg(not(feature = "production"))]
437 pub outputs: Vec<TransactionOutput>,
438 pub lock_time: Natural,
439}
440
441#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
446pub struct BlockHeader {
447 pub version: Integer,
448 pub prev_block_hash: Hash,
449 pub merkle_root: Hash,
450 pub timestamp: Natural,
451 pub bits: Natural,
452 pub nonce: Natural,
453}
454
455impl std::convert::AsRef<BlockHeader> for BlockHeader {
456 #[inline]
457 fn as_ref(&self) -> &BlockHeader {
458 self
459 }
460}
461
462#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
468pub struct Block {
469 pub header: BlockHeader,
470 pub transactions: Box<[Transaction]>,
471}
472
473#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
475pub struct UTXO {
476 pub value: Integer,
477 pub script_pubkey: SharedByteString,
478 pub height: Natural,
479 pub is_coinbase: bool,
482}
483
484#[cfg(feature = "production")]
489pub type UtxoSet = FxHashMap<OutPoint, std::sync::Arc<UTXO>>;
490
491#[cfg(not(feature = "production"))]
492pub type UtxoSet = HashMap<OutPoint, std::sync::Arc<UTXO>>;
493
494#[inline]
496pub fn utxo_set_insert(set: &mut UtxoSet, op: OutPoint, u: UTXO) {
497 use std::sync::Arc;
498 set.insert(op, Arc::new(u));
499}
500
501#[must_use = "Validation result must be checked - ignoring may cause consensus violations"]
506#[derive(Debug, Clone, PartialEq, Eq)]
507pub enum ValidationResult {
508 Valid,
509 Invalid(String),
510}
511
512#[derive(Debug, Clone)]
514pub struct ScriptContext {
515 pub script_sig: ByteString,
516 pub script_pubkey: ByteString,
517 pub witness: Option<ByteString>,
518 pub flags: u32,
519}
520
521#[derive(Debug, Clone)]
523pub struct BlockContext {
524 pub height: Natural,
525 pub prev_headers: Vec<BlockHeader>,
526 pub utxo_set: UtxoSet,
527}