-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathradon_error.rs
More file actions
183 lines (167 loc) · 6.58 KB
/
Copy pathradon_error.rs
File metadata and controls
183 lines (167 loc) · 6.58 KB
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
use std::io::Cursor;
use cbor::{types::Tag, value::Value as CborValue, GenericEncoder};
use failure::Fail;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use serde::Serialize;
use serde_cbor::Value as SerdeCborValue;
#[derive(Clone, Copy, Debug, Eq, IntoPrimitive, PartialEq, Serialize, TryFromPrimitive)]
#[repr(u8)]
/// List of RADON-level errors.
/// **WARNING: these codes are consensus-critical.** They can be renamed but they cannot be
/// re-assigned without causing a non-backwards-compatible protocol upgrade.
pub enum RadonErrors {
/// Unknown error. Something went really bad!
Unknown = 0x00,
// Script format errors
/// At least one of the source scripts is not a valid CBOR-encoded value.
SourceScriptNotCBOR = 0x01,
/// The CBOR value decoded from a source script is not an Array.
SourceScriptNotArray = 0x02,
/// The Array value decoded form a source script is not a valid RADON script.
SourceScriptNotRADON = 0x03,
// Complexity errors
/// The request contains too many sources.
RequestTooManySources = 0x10,
/// The script contains too many calls.
ScriptTooManyCalls = 0x11,
// Operator errors
/// The operator does not exist.
UnsupportedOperator = 0x20,
// Retrieval-specific errors
/// At least one of the sources could not be retrieved, but returned HTTP error.
HTTPError = 0x30,
/// Al least one of the sources could not be retrieved, timeout reached.
RetrieveTimeout = 0x31,
/// Value cannot be extracted from binary buffer
BufferIsNotValue = 0x32,
// Math errors
/// Math operator caused an underflow.
Underflow = 0x40,
/// Math operator caused an overflow.
Overflow = 0x41,
/// Tried to divide by zero.
DivisionByZero = 0x42,
// Other errors
/// Received zero reveals
NoReveals = 0x50,
/// Insufficient consensus in tally precondition clause
InsufficientConsensus = 0x51,
/// Received zero commits
InsufficientCommits = 0x52,
/// Generic error during tally execution
TallyExecution = 0x53,
/// Invalid reveal serialization (malformed reveals are converted to this value)
MalformedReveal = 0x60,
/// Failed to encode reveal
EncodeReveal = 0x61,
// Access errors
/// Tried to access a value from an index using an index that is out of bounds
ArrayIndexOutOfBounds = 0x70,
/// Tried to access a value from a map using a key that does not exist
MapKeyNotFound = 0x71,
// Bridge errors: errors that only belong in inter-client communication
/// Requests that cannot be parsed must always get this error as their result.
/// However, this is not a valid result in a Tally transaction, because invalid requests
/// are never included into blocks and therefore never get a Tally in response.
BridgeMalformedRequest = 0xE0,
/// The request is rejected on the grounds that it may cause the submitter to spend or stake an
/// amount of value that is unjustifiably high when compared with the reward they will be getting
BridgePoorIncentives = 0xE1,
/// The request result length exceeds a bridge contract defined limit
BridgeOversizedResult = 0xE2,
// This should not exist:
/// Some tally error is not intercepted but should
UnhandledIntercept = 0xFF,
}
/// Use `RadonErrors::Unknown` as the default value of `RadonErrors`.
impl Default for RadonErrors {
fn default() -> Self {
RadonErrors::Unknown
}
}
/// This trait identifies a structure that can be used as an error type for `RadonError` and
/// `RadonReport`.
pub trait ErrorLike: Clone + Fail {
/// Encode the error as an array of `SerdeCborValue`
fn encode_cbor_array(&self) -> Result<Vec<SerdeCborValue>, failure::Error>;
/// Decode the error from an array of `SerdeCborValue`
fn decode_cbor_array(
serde_cbor_array: Vec<SerdeCborValue>,
) -> Result<RadonError<Self>, failure::Error>;
}
/// This structure is aimed to be the error type for the `result` field of `witnet_data_structures::radon_report::Report`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct RadonError<IE>
where
IE: ErrorLike,
{
/// The original `RadError` that originated this `RadonError`
inner: IE,
}
/// Implementation of encoding and convenience methods for `RadonError`.
impl<IE> RadonError<IE>
where
IE: ErrorLike,
{
/// Simple factory for `RadonError`.
pub fn new(inner: IE) -> Self {
RadonError { inner }
}
/// Encode `RadonError` as tagged CBOR value with tag 39.
/// Returns the result as `CborValue`.
pub fn encode_tagged_value(&self) -> Result<CborValue, failure::Error> {
let values: Vec<CborValue> = self
.inner
.encode_cbor_array()?
.into_iter()
.map(|scv| {
// FIXME(#953): remove this conversion
try_from_serde_cbor_value_for_cbor_value(scv)
})
.collect();
Ok(CborValue::Tagged(
Tag::of(39),
Box::new(CborValue::Array(values)),
))
}
/// Encode `RadonErorr` as tagged CBOR value with tag 39.
/// Returns the result as bytes.
pub fn encode_tagged_bytes(&self) -> Result<Vec<u8>, failure::Error> {
let mut encoder = GenericEncoder::new(Cursor::new(Vec::new()));
encoder.value(&self.encode_tagged_value()?)?;
Ok(encoder.into_inner().into_writer().into_inner())
}
/// Get a reference to the inner error type
pub fn inner(&self) -> &IE {
&self.inner
}
/// Unwrap the inner error type
pub fn into_inner(self) -> IE {
self.inner
}
}
impl<IE> std::fmt::Display for RadonError<IE>
where
IE: ErrorLike,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "RadonError({:?})", self.inner)
}
}
/// Convert SerdeCborValue into CborValue
pub fn try_from_serde_cbor_value_for_cbor_value(serde_cbor_value: SerdeCborValue) -> CborValue {
// FIXME(#953): impl TryFrom<SerdeCborValue> for <CborValue>
let mut decoder = cbor::decoder::GenericDecoder::new(
cbor::Config::default(),
std::io::Cursor::new(serde_cbor::to_vec(&serde_cbor_value).unwrap()),
);
decoder.value().unwrap()
}
/// Convert CborValue into SerdeCborValue
pub fn try_from_cbor_value_for_serde_cbor_value(cbor_value: CborValue) -> SerdeCborValue {
// FIXME(#953): impl TryFrom<CborValue> for <SerdeCborValue>
let mut encoder = cbor::encoder::GenericEncoder::new(Cursor::new(Vec::new()));
encoder.value(&cbor_value).unwrap();
let buffer = encoder.into_inner().into_writer().into_inner();
serde_cbor::from_slice(&buffer).unwrap()
}