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);
}
}