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
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;

#[cfg(not(feature = "std"))]
use core::result::Result;

#[cfg(not(feature = "std"))]
use core::convert::AsRef;

use bitvec::prelude::BitVec;

use crate::merkle::get_root;

/// Different types of comparisions of Plasma Transactions.
///
/// Plasma Transactions form a DAG where only one pathway back to the origin is
/// considered valid. However, there may be multiple pathways, so it is important
/// to allow this behavior to be compared in order to understand which transaction
/// is legitimate.
///
/// # Note
/// This comparision is used in the history verification logic, as well as withdrawal
/// challenge detection logic. Different clients may have a privledged view of this
/// ordering, since transactions may be encrypted in some context and unencrypted in
/// others, which means relationships may differ depending on information privledge
/// of the client.
#[derive(Debug, PartialEq)]
pub enum TxnCmp {
    /// LHS & RHS are the same exact transaction
    Same,
    /// LHS is the parent of RHS
    Parent,
    /// RHS is the parent of LHS
    Child,
    /// LHS & RHS have same parent, but LHS is earlier
    EarlierSibling,
    /// LHS & RHS have same parent, but RHS is earlier
    LaterSibling,
    /// LHS & RHS are the same txn to two different receivers
    DoubleSpend,
    /// LHS & RHS have no relationship to each other
    Unrelated,
}

/// Plasma Cash Transaction trait for a given Token.
///
/// All the methods a Plasma Cash Transaction must implement to allow
/// transaction and history verification logic to work. This allows
/// custom transactions to be defined that allow significant customization
/// of the semantics of transactions while conforming to the Plasma Cash
/// specification, which creates safety in the Layer 1 ⇋ Layer 2 bridge.
/// 
/// # Note
/// The design of this trait was such that it could be flexible enough to
/// support both transparent and encrypted transactions. When used with
/// encrypted transactions, there may be a logical difference in handling
/// transactions verification between publicly accessible information and
/// privledged parties to the transaction, so that should be taken into
/// account when using this API.
///
/// # Example
/// Users of this API should should define this e.g.
/// ```ignore
/// struct Transaction { ... }
///
/// impl PlasmaCashTxn for Transaction { ... }
/// ```
pub trait PlasmaCashTxn {
    type HashType: AsRef<[u8]>;

    /// Needed to obtain the key for a Merkle Proof.
    fn token_id(&self) -> BitVec;

    /// Transaction is well-formed (implementation-specific).
    ///
    /// # Note
    /// This might be used for certain use-cases to verify zk proofs,
    /// whereas other use cases might have only signature validation.
    fn valid(&self) -> bool;

    /// Return "Leaf Hash" of this transaction.
    ///
    /// # Note
    /// The "Leaf Hash" may be the encoded transaction structure directly,
    /// or it may be a publicly accessible committment, as required for certain
    /// applications such as Zero Knowledge Proofs.
    ///
    /// Implementation is left up to the end user, but this must return a consistent
    /// hash for use in the Sparse Merkle Tree data structure that Plasma Cash
    /// is standardized around for it's key: value txn datastore.
    ///
    /// It does *not* have to match the hash function used for SMT proofs, but it must
    /// be consistent and of the same size as the hashes returned by `hash_fn()` for
    /// the smt proof validation to work.
    // TODO Validate security proof
    fn leaf_hash(&self) -> Self::HashType;

    /// Returns an empty leaf hash.
    ///
    /// Used for proofs of exclusion in txn trie.
    fn empty_leaf_hash() -> Self::HashType;

    /// Function used to verify proofs.
    fn hash_fn() -> (fn(&[u8]) -> Self::HashType);

    /// Returns the relationship of another transaction (other) to this
    /// one (self).
    ///
    /// See [TxnCmp](enum.TxnCmp.html) enum definition for more information.
    fn compare(&self, other: &Self) -> TxnCmp;

    /// Obtain the root hash following the SMT algorithm.
    ///
    /// # Note
    /// Proof must be in un-compressed form (`proof.len() == smt.depth()`)
    fn get_root(&self, proof: Vec<Self::HashType>) -> Result<Self::HashType, &'static str> {
        get_root(&self.token_id(), self.leaf_hash(), proof, Self::hash_fn())
    }
}