simplicity/jet/elements/
environment.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
149
150
151
152
153
154
155
156
157
// SPDX-License-Identifier: CC0-1.0

use crate::merkle::cmr::Cmr;
use elements::confidential;
use elements::taproot::ControlBlock;
use simplicity_sys::c_jets::c_env::CElementsTxEnv;
use std::ops::Deref;

use super::c_env;

/// An Elements UTXO
// This is not a complete TxOut as it does not contain the nonce that
// is sent to the recipient.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ElementsUtxo {
    /// The 'scriptpubkey' (hash of Simplicity program)
    pub script_pubkey: elements::Script,
    /// The explicit or confidential asset
    pub asset: confidential::Asset,
    /// The explict or confidential value
    pub value: confidential::Value,
}

impl From<elements::TxOut> for ElementsUtxo {
    fn from(txout: elements::TxOut) -> Self {
        ElementsUtxo {
            script_pubkey: txout.script_pubkey,
            asset: txout.asset,
            value: txout.value,
        }
    }
}

/// Environment for Elements Simplicity
///
/// # Note
/// The order of `utxos` must be same as of the order of inputs in the
/// transaction.
#[derive(Debug)]
pub struct ElementsEnv<T: Deref<Target = elements::Transaction>> {
    /// The CTxEnv struct
    c_tx_env: CElementsTxEnv,
    /// The elements transaction
    tx: T,
    /// the current index of the input
    ix: u32,
    /// Control block used to spend this leaf script
    control_block: ControlBlock,
    /// Optional Annex.
    annex: Option<Vec<u8>>,
    /// Genesis block hash
    genesis_hash: elements::BlockHash,
}

impl<T> ElementsEnv<T>
where
    T: Deref<Target = elements::Transaction>,
{
    pub fn new(
        tx: T,
        utxos: Vec<ElementsUtxo>,
        ix: u32,
        script_cmr: Cmr,
        control_block: ControlBlock,
        annex: Option<Vec<u8>>,
        genesis_hash: elements::BlockHash,
    ) -> Self {
        let c_tx = c_env::new_tx(&tx, &utxos);
        let c_tap_env = c_env::new_tap_env(&control_block, script_cmr);
        let c_tx_env = c_env::new_tx_env(c_tx, c_tap_env, genesis_hash, ix);
        ElementsEnv {
            c_tx_env,
            tx,
            ix,
            control_block,
            annex,
            genesis_hash,
        }
    }

    /// Obtains the FFI compatible CTxEnv from self
    pub fn c_tx_env(&self) -> &CElementsTxEnv {
        &self.c_tx_env
    }

    /// Returns the transaction of this environment
    pub fn tx(&self) -> &elements::Transaction {
        &self.tx
    }

    /// Returns the input index of this environment
    pub fn ix(&self) -> u32 {
        self.ix
    }

    /// Returns a reference to the control block of this [`ElementsEnv`].
    pub fn control_block(&self) -> &ControlBlock {
        &self.control_block
    }

    /// Returns the annex of this [`ElementsEnv`].
    pub fn annex(&self) -> Option<&Vec<u8>> {
        self.annex.as_ref()
    }

    /// Returns the genesis hash of this [`ElementsEnv`].
    pub fn genesis_hash(&self) -> elements::BlockHash {
        self.genesis_hash
    }
}

#[cfg(test)]
impl ElementsEnv<std::sync::Arc<elements::Transaction>> {
    /// Return a dummy Elements environment
    pub fn dummy() -> Self {
        Self::dummy_with(elements::LockTime::ZERO, elements::Sequence::MAX)
    }

    /// Return a dummy Elements environment with given locktime
    pub fn dummy_with(lock_time: elements::LockTime, sequence: elements::Sequence) -> Self {
        use elements::AssetIssuance;
        use hashes::Hash;

        let ctrl_blk: [u8; 33] = [
            0xc0, 0xeb, 0x04, 0xb6, 0x8e, 0x9a, 0x26, 0xd1, 0x16, 0x04, 0x6c, 0x76, 0xe8, 0xff,
            0x47, 0x33, 0x2f, 0xb7, 0x1d, 0xda, 0x90, 0xff, 0x4b, 0xef, 0x53, 0x70, 0xf2, 0x52,
            0x26, 0xd3, 0xbc, 0x09, 0xfc,
        ];

        ElementsEnv::new(
            std::sync::Arc::new(elements::Transaction {
                version: 2,
                lock_time,
                // Enable locktime in dummy txin
                input: vec![elements::TxIn {
                    previous_output: elements::OutPoint::default(),
                    is_pegin: false,
                    script_sig: elements::Script::new(),
                    sequence,
                    asset_issuance: AssetIssuance::default(),
                    witness: elements::TxInWitness::default(),
                }],
                output: Vec::default(),
            }),
            vec![ElementsUtxo {
                script_pubkey: elements::Script::new(),
                asset: confidential::Asset::Null,
                value: confidential::Value::Null,
            }],
            0,
            Cmr::from_byte_array([0; 32]),
            ControlBlock::from_slice(&ctrl_blk).unwrap(),
            None,
            elements::BlockHash::all_zeros(),
        )
    }
}