-
Notifications
You must be signed in to change notification settings - Fork 18
/
verifier.rs
148 lines (123 loc) · 4.88 KB
/
verifier.rs
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! A verifier is a piece of logic that determines whether an input can be consumed in a given context.
//! Because there are multiple reasonable ways to make this decision, we expose a trait to encapsulate
//! the various options. Each runtime will choose to make one or more verifiers available to its users
//! and they will be aggregated into an enum. The most common and useful verifiers are included here
//! with Tuxedo core, but downstream developers are expected to create their own as well.
//!
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
use sp_std::fmt::Debug;
mod htlc;
mod multi_signature;
mod simple_signature;
pub use htlc::{BlakeTwoHashLock, TimeLock};
pub use multi_signature::ThresholdMultiSignature;
pub use simple_signature::{Sr25519Signature, P2PKH};
/// A means of checking that an output can be spent. This check is made on a
/// per-output basis and neither knows nor cares anything about the validation logic that will
/// be applied to the transaction as a whole. Nonetheless, in order to avoid malleability, we
/// we take the entire stripped and serialized transaction as a parameter.
///
/// Information available when verifying an input includes:
/// * The simplified transaction - a stripped encoded version of the transaction
/// * Some environmental information such as the block current block number
/// * An redeemer supplied by the user attempting to spend the input.
pub trait Verifier: Debug + Encode + Decode + Clone {
/// The type that will be supplied to satisfy the verifier and redeem the UTXO.
type Redeemer: Debug + Encode + Decode;
/// Main function in the trait. Does the checks to make sure an output can be spent.
fn verify(&self, simplified_tx: &[u8], block_height: u32, redeemer: &Self::Redeemer) -> bool;
/// A way to create a new instance of the verifier whose semantics cannot be spent.
/// This may be a signature check with a pubkey of 0 or a hashlock with a hash o 0
/// or a bitcoin script that directly returns false, etc.
///
/// This is only required in chains that use inherents, and thus a default implementation
/// is provided.
fn new_unspendable() -> Option<Self> {
log::debug!(
target: crate::LOG_TARGET,
"In new_unspendable default function implementation. About to return hardcoded `None`."
);
None
}
}
/// A simple verifier that allows anyone to consume an output at any time
#[derive(
Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo, Default,
)]
pub struct UpForGrabs;
impl Verifier for UpForGrabs {
type Redeemer = ();
fn verify(&self, _simplified_tx: &[u8], _: u32, _: &()) -> bool {
true
}
}
/// A simple verifier that allows no one to consume an output ever.
///
/// This is useful for UTXOs that are expected to only ever be consumed by evictions,
/// such as inherents for example.
#[derive(
Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo, Default,
)]
pub struct Unspendable;
impl Verifier for Unspendable {
type Redeemer = ();
fn verify(&self, _simplified_tx: &[u8], _: u32, _: &()) -> bool {
false
}
fn new_unspendable() -> Option<Self> {
Some(Self)
}
}
// Idea: It could be useful to allow delay deciding whether the redemption should succeed
// until spend-time. In that case you could pass it in as a verifier.
/// A testing verifier that passes or depending on the enclosed
/// boolean value.
#[cfg(feature = "std")]
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
pub struct TestVerifier {
/// Whether the verifier should pass
pub verifies: bool,
}
#[cfg(feature = "std")]
impl Verifier for TestVerifier {
type Redeemer = ();
fn verify(&self, _simplified_tx: &[u8], _: u32, _: &()) -> bool {
self.verifies
}
fn new_unspendable() -> Option<Self> {
Some(Self { verifies: false })
}
}
#[cfg(test)]
mod test {
use super::*;
use sp_core::{crypto::Pair as _, sr25519::Pair};
/// Generate a bunch of test keypairs
pub(crate) fn generate_n_pairs(n: u8) -> Vec<Pair> {
let mut seed = [0u8; 32];
let mut pairs = Vec::new();
// We generate the pairs from sequential seeds. Just changing the last byte of the seed each time.
for i in 0..n {
seed[31] = i;
let pair = Pair::from_seed(&seed);
pairs.push(pair);
}
pairs
}
#[test]
fn up_for_grabs_always_verifies() {
assert!(UpForGrabs.verify(&[], 0, &()))
}
#[test]
fn test_verifier_passes() {
let result = TestVerifier { verifies: true }.verify(&[], 0, &());
assert!(result);
}
#[test]
fn test_verifier_fails() {
let result = TestVerifier { verifies: false }.verify(&[], 0, &());
assert!(!result);
}
}