1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Descriptor wallet library extending bitcoin & miniscript functionality
// by LNP/BP Association (https://lnp-bp.org)
// Written in 2020-2021 by
// Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the Apache-2.0 License
// along with this software.
// If not, see <https://opensource.org/licenses/Apache-2.0>.
// In the future this mod will probably become part of bitcoin library
// Coding conventions
//! # Bitcoin script types
//!
//! Bitcoin doesn't make a distinction between Bitcoin script coming from
//! different sources, like *scriptPubKey* in transaction output or witness and
//! *sigScript* in transaction input. There are many other possible script
//! containers for Bitcoin script: redeem script, witness script, tapscript. In
//! fact, any "script" of [`bitcoin::Script`] type can be used for inputs and
//! outputs. What is a valid script for one will be a valid script for the
//! other; the only req. is formatting of opcodes & pushes. That would mean that
//! in principle every input script can be used as an output script, but not
//! vice versa. But really what makes a "script" is just the fact that it's
//! formatted correctly.
//!
//! While all `Script`s represent the same type **semantically**, there is a
//! clear distinction at the **logical** level: Bitcoin script has the property
//! to be committed into some other Bitcoin script – in a nested structures like
//! in several layers, like *redeemScript* inside of *sigScript* used for P2SH,
//! or *tapScript* within *witnessScript* coming from *witness* field
//! for Taproot. These nested layers do distinguish on the information they
//! contain, since some of them only commit to the hashes of the nested scripts
//! ([`bitcoin::ScriptHash`], [`WitnessProgram`]) or public keys
//! ([`bitcoin::PubkeyHash`], [`bitcoin::WPubkeyHash`]), while other contain the
//! full source of the script.
//!
//! The present type system represents a solution to the problem: it distinguish
//! different logical types by introducing `Script` wrapper types. It defines
//! [`LockScript`] as bottom layer of a script hierarchy, containing no other
//! script commitments (in form of their hashes). It also defines types above on
//! it: [`PubkeyScript`] (for whatever is there in `scriptPubkey` field of a
//! `TxOut`), [`SigScript`] (for whatever comes from `sigScript` field of
//! [`bitcoin::TxIn`]), [`RedeemScript`] and [`TapScript`]. Then, there are
//! conversion functions, which, for instance, can analyse [`PubkeyScript`] and
//! if it is a custom script or P2PK return a [`LockScript`] type - or otherwise
//! fail with error. So with this type system one is always sure which logical
//! information it does contain.
//!
//! ## Type derivation
//!
//! The following charts represent possible relations between script types:
//!
//! ```text
//! LockScript
//! _________________________________
//! ^ ^ ^ ^ ^
//! | | | | |
//! [txout.scriptPubKey] <===> PubkeyScript --?--/P2PK & custom/---+ | | | |
//! | | | |
//! [txin.sigScript] <===> SigScript --+--?!--/P2(W)PKH/--(#=PubkeyHash)--+ | | |
//! | | | |
//! | (#=ScriptHash) | |
//! | | | |
//! +--?!--> RedeemScript --+--?!------/P2SH/ | |
//! | | |
//! /P2WSH-in-P2SH/ /#=V0_WitnessProgram_P2WSH/ |
//! | | |
//! +--?!--> WitnessScript |
//! ^^ | |
//! || /#=V1_WitnessProgram/ |
//! || | |
//! [?txin.witness] <=====================================================++ +--?---> TapScript
//! ```
//!
//! Legend:
//! * `[source] <===> `: data source
//! * `[?source] <===> `: data source which may be absent
//! * `--+--`: algorithmic branching (alternative computation options)
//! * `--?-->`: a conversion exists, but it may fail (returns [`Option`] or
//! [`Result`])
//! * `--?!-->`: a conversion exists, but it may fail; however one of
//! alternative branches must always succeed
//! * `----->`: a conversion exists which can't fail
//! * `--/format/--`: a format implied by scriptPubKey program
//! * `--(#=type)--`: the hash of the value following `->` must match to the
//! value of the `<type>`
//!
//! ## Type conversion
//!
//! ```text
//! LockScript -+-> (PubkeyScript + RedeemScript) -+-> SigScript
//! | +-> WitnessScript
//! +-> PubkeyScript
//! |
//! +-> TapScript
//!
//! PubkeyScript --?--> LockScript
//! ```
extern crate amplify;
extern crate strict_encoding;
pub use Category;
pub use PubkeyParseError;
pub use ;