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 = 25;
73
74#[derive(Clone)]
75enum SharedRepr {
76 Inline {
77 len: u8,
78 data: [u8; SHARED_BYTE_INLINE_CAP],
79 },
80 Shared(std::sync::Arc<[u8]>),
81}
82
83#[derive(Clone)]
86pub struct SharedByteString(SharedRepr);
87
88impl std::fmt::Debug for SharedByteString {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 f.debug_tuple("SharedByteString")
91 .field(&self.as_slice())
92 .finish()
93 }
94}
95
96impl PartialEq for SharedByteString {
97 #[inline]
98 fn eq(&self, other: &Self) -> bool {
99 self.as_slice() == other.as_slice()
100 }
101}
102
103impl Eq for SharedByteString {}
104
105impl std::hash::Hash for SharedByteString {
106 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
107 self.as_slice().hash(state);
108 }
109}
110
111impl SharedByteString {
112 #[inline]
113 fn as_slice(&self) -> &[u8] {
114 match &self.0 {
115 SharedRepr::Inline { len, data } => &data[..*len as usize],
116 SharedRepr::Shared(a) => a,
117 }
118 }
119
120 #[inline]
121 fn from_bytes(v: &[u8]) -> Self {
122 if v.len() <= SHARED_BYTE_INLINE_CAP {
123 let mut data = [0u8; SHARED_BYTE_INLINE_CAP];
124 data[..v.len()].copy_from_slice(v);
125 Self(SharedRepr::Inline {
126 len: v.len() as u8,
127 data,
128 })
129 } else {
130 Self(SharedRepr::Shared(std::sync::Arc::from(v)))
131 }
132 }
133}
134
135impl std::ops::Deref for SharedByteString {
136 type Target = [u8];
137 #[inline]
138 fn deref(&self) -> &[u8] {
139 self.as_slice()
140 }
141}
142
143impl Serialize for SharedByteString {
144 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
145 self.as_slice().serialize(s)
146 }
147}
148
149impl<'de> Deserialize<'de> for SharedByteString {
150 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
151 let v: Vec<u8> = Deserialize::deserialize(d)?;
152 Ok(Self::from_bytes(&v))
153 }
154}
155
156impl From<ByteString> for SharedByteString {
157 #[inline]
158 fn from(v: ByteString) -> Self {
159 Self::from_bytes(v.as_slice())
160 }
161}
162
163impl From<&[u8]> for SharedByteString {
164 #[inline]
165 fn from(v: &[u8]) -> Self {
166 Self::from_bytes(v)
167 }
168}
169
170impl Default for SharedByteString {
171 #[inline]
172 fn default() -> Self {
173 Self(SharedRepr::Inline {
174 len: 0,
175 data: [0u8; SHARED_BYTE_INLINE_CAP],
176 })
177 }
178}
179
180impl AsRef<[u8]> for SharedByteString {
181 #[inline]
182 fn as_ref(&self) -> &[u8] {
183 self.as_slice()
184 }
185}
186
187impl SharedByteString {
188 #[inline]
190 pub fn as_arc(&self) -> std::sync::Arc<[u8]> {
191 match &self.0 {
192 SharedRepr::Shared(a) => std::sync::Arc::clone(a),
193 SharedRepr::Inline { len, data } => {
194 std::sync::Arc::from(data[..*len as usize].to_vec().into_boxed_slice())
195 }
196 }
197 }
198}
199
200pub type Natural = u64;
202
203pub type Integer = i64;
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
210pub enum Network {
211 Mainnet,
213 Testnet,
215 Regtest,
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq)]
224pub struct TimeContext {
225 pub network_time: u64,
228 pub median_time_past: u64,
231}
232
233#[derive(Debug, Clone, Copy, PartialEq, Eq)]
240pub struct Bip54BoundaryTimestamps {
241 pub timestamp_n_minus_1: u64,
243 pub timestamp_n_minus_2015: u64,
245}
246
247#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
252pub enum ForkId {
253 Bip30,
255 Bip16,
257 Bip34,
259 Bip66,
261 Bip65,
263 Bip112,
265 Bip147,
267 SegWit,
269 Taproot,
271 Ctv,
273 Csfs,
275 Bip54,
277}
278
279impl Network {
280 pub fn from_env() -> Self {
287 match std::env::var("BITCOIN_NETWORK").as_deref() {
288 Ok("testnet") => Network::Testnet,
289 Ok("regtest") => Network::Regtest,
290 _ => Network::Mainnet,
291 }
292 }
293
294 pub fn hrp(&self) -> &'static str {
298 match self {
299 Network::Mainnet => "bc",
300 Network::Testnet => "tb",
301 Network::Regtest => "bcrt",
302 }
303 }
304}
305
306#[repr(transparent)]
311#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
312pub struct BlockHeight(pub u64);
313
314impl BlockHeight {
315 #[inline(always)]
317 pub fn new(height: u64) -> Self {
318 BlockHeight(height)
319 }
320
321 #[inline(always)]
323 pub fn as_u64(self) -> u64 {
324 self.0
325 }
326}
327
328impl From<u64> for BlockHeight {
329 #[inline(always)]
330 fn from(height: u64) -> Self {
331 BlockHeight(height)
332 }
333}
334
335impl From<BlockHeight> for u64 {
336 #[inline(always)]
337 fn from(height: BlockHeight) -> Self {
338 height.0
339 }
340}
341
342impl std::ops::Deref for BlockHeight {
343 type Target = u64;
344
345 #[inline(always)]
346 fn deref(&self) -> &Self::Target {
347 &self.0
348 }
349}
350
351#[repr(transparent)]
356#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
357pub struct BlockHash(pub Hash);
358
359impl BlockHash {
360 #[inline(always)]
362 pub fn new(hash: Hash) -> Self {
363 BlockHash(hash)
364 }
365
366 #[inline(always)]
368 pub fn as_hash(self) -> Hash {
369 self.0
370 }
371
372 #[inline(always)]
374 pub fn as_hash_ref(&self) -> &Hash {
375 &self.0
376 }
377}
378
379impl From<Hash> for BlockHash {
380 #[inline(always)]
381 fn from(hash: Hash) -> Self {
382 BlockHash(hash)
383 }
384}
385
386impl From<BlockHash> for Hash {
387 #[inline(always)]
388 fn from(hash: BlockHash) -> Self {
389 hash.0
390 }
391}
392
393impl std::ops::Deref for BlockHash {
394 type Target = Hash;
395
396 #[inline(always)]
397 fn deref(&self) -> &Self::Target {
398 &self.0
399 }
400}
401
402#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
406pub struct OutPoint {
407 pub hash: Hash,
408 pub index: u32,
409}
410
411#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
416pub struct TransactionInput {
417 pub prevout: OutPoint, pub sequence: Natural, pub script_sig: ByteString, }
421
422#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
424pub struct TransactionOutput {
425 pub value: Integer,
426 pub script_pubkey: ByteString,
427}
428
429#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
434pub struct Transaction {
435 pub version: Natural,
436 #[cfg(feature = "production")]
437 pub inputs: SmallVec<[TransactionInput; 2]>,
438 #[cfg(not(feature = "production"))]
439 pub inputs: Vec<TransactionInput>,
440 #[cfg(feature = "production")]
441 pub outputs: SmallVec<[TransactionOutput; 2]>,
442 #[cfg(not(feature = "production"))]
443 pub outputs: Vec<TransactionOutput>,
444 pub lock_time: Natural,
445}
446
447#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
452pub struct BlockHeader {
453 pub version: Integer,
454 pub prev_block_hash: Hash,
455 pub merkle_root: Hash,
456 pub timestamp: Natural,
457 pub bits: Natural,
458 pub nonce: Natural,
459}
460
461impl std::convert::AsRef<BlockHeader> for BlockHeader {
462 #[inline]
463 fn as_ref(&self) -> &BlockHeader {
464 self
465 }
466}
467
468#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
474pub struct Block {
475 pub header: BlockHeader,
476 pub transactions: Box<[Transaction]>,
477}
478
479#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
481pub struct UTXO {
482 pub value: Integer,
483 pub script_pubkey: SharedByteString,
484 pub height: Natural,
485 pub is_coinbase: bool,
488}
489
490#[cfg(feature = "production")]
495pub type UtxoSet = FxHashMap<OutPoint, std::sync::Arc<UTXO>>;
496
497#[cfg(not(feature = "production"))]
498pub type UtxoSet = HashMap<OutPoint, std::sync::Arc<UTXO>>;
499
500#[inline]
504pub fn utxo_set_with_capacity(n: usize) -> UtxoSet {
505 #[cfg(feature = "production")]
506 {
507 FxHashMap::with_capacity_and_hasher(n, Default::default())
508 }
509 #[cfg(not(feature = "production"))]
510 {
511 HashMap::with_capacity(n)
512 }
513}
514
515#[inline]
517pub fn utxo_set_insert(set: &mut UtxoSet, op: OutPoint, u: UTXO) {
518 use std::sync::Arc;
519 set.insert(op, Arc::new(u));
520}
521
522#[must_use = "Validation result must be checked - ignoring may cause consensus violations"]
527#[derive(Debug, Clone, PartialEq, Eq)]
528pub enum ValidationResult {
529 Valid,
530 Invalid(String),
531}
532
533#[derive(Debug, Clone)]
535pub struct ScriptContext {
536 pub script_sig: ByteString,
537 pub script_pubkey: ByteString,
538 pub witness: Option<ByteString>,
539 pub flags: u32,
540}
541
542#[derive(Debug, Clone)]
544pub struct BlockContext {
545 pub height: Natural,
546 pub prev_headers: Vec<BlockHeader>,
547 pub utxo_set: UtxoSet,
548}