blockchain_traits/
lib.rs

1#![feature(non_exhaustive)]
2
3use oasis_types::{AccountMeta, Address, Event};
4
5pub trait Blockchain {
6    /// Returns the name of this blockchain.
7    fn name(&self) -> &str;
8
9    /// Returns the block at a given height.
10    fn block(&self, height: usize) -> Option<&dyn Block>;
11
12    /// Returns a reference to the block at the current maximum height.
13    fn last_block(&self) -> &dyn Block;
14
15    /// Returns a mutable reference to the block at the current maximum height.
16    fn last_block_mut(&mut self) -> &mut dyn Block;
17}
18
19pub trait Block {
20    /// Returns the height of this block.
21    fn height(&self) -> u64;
22
23    /// Executes a RPC to `callee` with provided `input` and `gas` computational resources.
24    /// `value` tokens will be transferred from the `caller` to the `callee`.
25    /// The `caller` is charged `gas * gas_price` for the computation.
26    /// A transaction that aborts (panics) will have its changes rolled back.
27    /// This `transact` should be called by an Externally Owned Account (EOA).
28    #[allow(clippy::too_many_arguments)]
29    fn transact(
30        &mut self,
31        caller: Address,
32        callee: Address,
33        payer: Address,
34        value: u128,
35        input: &[u8],
36        gas: u64,
37        gas_price: u64,
38    ) -> Box<dyn Receipt>;
39
40    /// Returns the bytecode stored at `addr` or `None` if the account does not exist.
41    fn code_at(&self, addr: &Address) -> Option<&[u8]>;
42
43    /// Returns the metadata of the account stored at `addr`, or
44    /// `None` if the account does not exist.
45    fn account_meta_at(&self, addr: &Address) -> Option<AccountMeta>;
46
47    /// Returns the state of the account at `addr`, if it exists.
48    fn state_at(&self, addr: &Address) -> Option<&dyn KVStore>;
49
50    /// Returns the events emitted during the course of this block.
51    fn events(&self) -> Vec<&Event>;
52
53    /// Returns the receipts of transactions executed in this block.
54    fn receipts(&self) -> Vec<&dyn Receipt>;
55}
56
57/// Represents the data and functionality available to a smart contract execution.
58pub trait PendingTransaction {
59    /// Returns the address of the current contract instance.
60    fn address(&self) -> &Address;
61
62    /// Returns the address of the sender of the transaction.
63    fn sender(&self) -> &Address;
64
65    /// Returns the value sent to the current transaction.
66    fn value(&self) -> u128;
67
68    /// Returns the input provided by the calling context.
69    fn input(&self) -> &[u8];
70
71    /// Creates a new contract with the provided code and initial value.
72    /// The new transaction will inherit the gas parameters and gas payer of the top level
73    /// transaction. The current account will be set as the sender.
74    fn create(&mut self, value: u128, code: &[u8]) -> Box<dyn Receipt>;
75
76    /// Executes a balance-transferring RPC to `callee` with provided input and value.
77    /// The new transaction will inherit the gas parameters and gas payer of the top level
78    /// transaction. The current account will be set as the sender.
79    fn transact(&mut self, callee: Address, value: u128, input: &[u8]) -> Box<dyn Receipt>;
80
81    /// Returns data to the calling transaction.
82    fn ret(&mut self, data: &[u8]);
83
84    /// Returns error data to the calling context.
85    fn err(&mut self, data: &[u8]);
86
87    /// Publishes a broadcast message in this block.
88    fn emit(&mut self, topics: &[&[u8]], data: &[u8]);
89
90    /// Returns the state of the current account.
91    fn state(&self) -> &dyn KVStore;
92
93    /// Returns the mutable state of the current account.
94    fn state_mut(&mut self) -> &mut dyn KVStoreMut;
95
96    /// Returns the bytecode stored at `addr` or `None` if the account does not exist.
97    fn code_at(&self, addr: &Address) -> Option<&[u8]>;
98
99    /// Returns the metadata of the account stored at `addr`, or
100    /// `None` if the account does not exist.
101    fn account_meta_at(&self, addr: &Address) -> Option<AccountMeta>;
102}
103
104/// Interface for a Blockchain-flavored key-value store.
105pub trait KVStore {
106    /// Returns whether the key is present in account storage.
107    fn contains(&self, key: &[u8]) -> bool;
108
109    /// Returns the data stored in the account at `addr` under the given `key`.
110    fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
111}
112
113pub trait KVStoreMut: KVStore {
114    /// Sets the data stored in the account under the given  `key`.
115    /// Overwrites any existing data.
116    fn set(&mut self, key: &[u8], value: &[u8]);
117
118    /// Removes the data stored in the account under the given  `key`.
119    fn remove(&mut self, key: &[u8]);
120}
121
122pub trait Receipt {
123    fn caller(&self) -> &Address;
124
125    fn callee(&self) -> &Address;
126
127    /// Returns the total gas used during the execution of the transaction.
128    fn gas_used(&self) -> u64;
129
130    /// Returns the events emitted during the transaction.
131    fn events(&self) -> Vec<&Event>;
132
133    /// Returns the outcome of this transaction.
134    fn outcome(&self) -> TransactionOutcome;
135
136    /// Returns the output of the transaction.
137    fn output(&self) -> &[u8];
138
139    /// Returns whether the transaction that produced this receipt was reverted.
140    fn reverted(&self) -> bool {
141        match self.outcome() {
142            TransactionOutcome::Success => false,
143            _ => true,
144        }
145    }
146}
147
148#[derive(Clone, Copy, PartialEq, Eq, Debug)]
149#[non_exhaustive]
150#[repr(u16)]
151pub enum TransactionOutcome {
152    Success,
153    InsufficientFunds,
154    InsufficientGas,
155    InvalidInput,
156    InvalidCallee,
157    Aborted, // recoverable error
158    Fatal,
159}
160
161impl TransactionOutcome {
162    pub fn reverted(self) -> bool {
163        match self {
164            TransactionOutcome::Success => false,
165            _ => true,
166        }
167    }
168}