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}