Skip to content

Commit 35a3039

Browse files
Bartosz Lenartbartossh
andauthored
Implement lacking ts equality check in payload. (#30)
### References [TASK RDS-2005](https://redstone-team.atlassian.net/browse/RDS-2005) Implements check against payload timestamps being equal. --------- Co-authored-by: bartossh <bartosz.lenart@redstone.com>
1 parent 667ae41 commit 35a3039

File tree

6 files changed

+173
-70
lines changed

6 files changed

+173
-70
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# RustSDK - Audit guide
22

3+
This repository is an integral part of the https://github.com/redstone-finance/redstone-oracles-monorepo repository,
4+
especially of the solana-connector package (https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/solana-connector) and is subject of all their licenses.
5+
36
<!-- TOC -->
47

58
- [RustSDK - Audit guide](#rustsdk---audit-guide)
@@ -26,11 +29,11 @@ The direct path should look like:
2629

2730
### Documentation
2831

29-
- Redstone crate documentation [./crates/redstone/README.md](./crates/redstone/README.md)
30-
- RedstoneConfig is abstraction required as configuration for the RedStone protocol.
31-
[redstone/trait.RedStoneConfig](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/trait.RedStoneConfig.html)
32+
- Redstone crate documentation [here](./crates/redstone/README.md)
33+
- RedstoneConfig is abstraction required as configuration for the RedStone protocol
34+
[here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/trait.RedStoneConfig.html).
3235
- Process Payload function is the main processor of the RedStone payload
33-
[redstone/core/processor/fn.process_payload](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor/fn.process_payload.html)
36+
[here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor/fn.process_payload.html).
3437
- General [RedStone Blockchain Oracles docs](https://docs.redstone.finance/docs/get-started/data-formatting-processing/)
3538
- Especially [The push model docs](https://docs.redstone.finance/docs/get-started/models/redstone-push/)
3639

crates/redstone/README.md

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,63 +14,55 @@
1414

1515
## Rust SDK Overview
1616

17-
The main documentation page [rust/redstone/rust_sdk_2/redstone/index.html](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/index.html)
17+
The main documentation page [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/index.html)
1818
lists the collection of utilities to make deserializing and decrypting RedStone payload as well as
1919
the Rust based blockchain utils, cryptographic methods, network and contract primitives.
2020

2121
## Network
2222

2323
Network module contains primitives that allow to communicate via processor module with clear interface giving clear `Error` messages
24-
and `Environment` trait all in one place [rust/redstone/rust_sdk_2/redstone/network](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/network/index.html).
24+
and `Environment` trait all in one place [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/network/index.html).
2525

2626
## Configuration
2727

28-
Configuration module contains configuration for the RedStone payload processor [rust/redstone/rust_sdk_2/redstone/core/config](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/config/index.html).
28+
Configuration module contains configuration for the RedStone payload processor [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/config/index.html).
2929

3030
- Configuration for the RedStone Rust-SDK is given as a pluggable entity. Any type implementing RedStoneConfig trait
31-
is a valid type to be used as config [redstone/trait.RedStoneConfig](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/trait.RedStoneConfig.html)
31+
is a valid type to be used as config [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/trait.RedStoneConfig.html)
3232
Configuration requires to allow for perforimng two actions and to provide the Config type:
3333
- Crypto operations needed for address recovery. Different blockchains requires different cryptographic flavors.
3434
- Environment in which we execute. Provides logging etc. The same situation of flavors applies for the Environment.
3535
- Please check specific blockchain module for the implementation of Crypto and Environment modules:
36-
- Default [rust/redstone/rust_sdk_2/redstone/default_ext](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/default_ext/index.html)
37-
- Solana [rust/redstone/rust_sdk_2/redstone/solana](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/solana/index.html)
38-
- Radix [/rust/redstone/rust_sdk_2/redstone/radix](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/radix/index.html)
39-
- Casper [rust/redstone/rust_sdk_2/redstone/casper](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/casper/index.html)
36+
- Default [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/default_ext/index.html)
37+
- Solana [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/solana/index.html)
38+
- Radix [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/radix/index.html)
39+
- Casper [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/casper/index.html)
4040
- Config type - configuration for a RedStone payload processor.
41-
Specifies the parameters necessary for the verification and aggregation of values from various data points passed by the RedStone payload.
42-
[rust/redstone/rust_sdk_2/redstone/core/config/struct.Config](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/config/struct.Config.html)
41+
Specifies the parameters necessary for the verification and aggregation of values from various data points passed by the RedStone payload
42+
[here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/config/struct.Config.html).
4343

4444
## Processor
4545

46-
Processor module contains the main processor of the RedStone payload [rust/redstone/rust_sdk_2/redstone/core/processor](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor/index.html).
46+
Processor module contains the main processor of the RedStone payload [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor/index.html).
4747

48-
- To proses payload use `process_payload` function in processor module
49-
[rust/redstone/rust_sdk_2/redstone/core/processor/fn.process_payload.html](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor/fn.process_payload.html)
48+
- To process payload use `process_payload` function in processor module
49+
[here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor/fn.process_payload.html) and its the main entrypoint in the core::processor module.
50+
It parses payload-bytes to DataPackages, consisting of DataPoints, see: https://docs.redstone.finance/img/payload.png
51+
each DataPackage is signed by a signer, to be recovered having the DataPackage's data and the signature (both are included in the payload-bytes).
52+
The recovering is important in the aggregation process: only the data signed by trusted signers (part of z Config) are counted to the aggregation (median value),
53+
it also validates timestamps (if they're not too old/far/future and all shall be equal).
54+
The aggregation (median values) is based on building a matrix: for each feed_id (in rows) from the Config the values for particular trusted signers in columns (taken by their indices).
5055
- The `config` argument is described above Configuration.
51-
- The `payload` argument is type that is convertible to bytes (Vec<u8>), and the bytes encoding is described in
52-
[redstone.finance docs data-formatting-processing](https://docs.redstone.finance/docs/get-started/data-formatting-processing/#how-data-is-encoded-before-being-put-on-the-blockchain)
53-
- The result of `process_payload` [rust/redstone/rust_sdk_2/redstone/core/processor_result/type.ProcessorResult](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor_result/type.ProcessorResult.html)
56+
- The `payload` argument is type that is convertible to bytes (Vec<u8>), and the bytes encoding is described in Redstone Finance Docs:
57+
[data formatting](https://docs.redstone.finance/docs/get-started/data-formatting-processing/#how-data-is-encoded-before-being-put-on-the-blockchain).
58+
- The result of `process_payload` [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor_result/type.ProcessorResult.html)
5459
returns success or an error:
55-
- Success contains a validated payload [rust/redstone/rust_sdk_2/redstone/core/processor_result/struct.ValidatedPayload](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor_result/struct.ValidatedPayload.html)
60+
- Success contains a validated payload [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/core/processor_result/struct.ValidatedPayload.html)
5661
containing a `min_timestamp` in [ ms ] which is the minimum timestamp encountered during processing and `values` (`Vec<Value>`)
57-
where [rust/redstone/rust_sdk_2/redstone/struct.Value](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/struct.Value.html)
62+
where Value [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/struct.Value.html)
5863
Each element in this vector represents a processed value corresponding to the passed data_feed item in the Config
5964

6065
## Contract
6166

62-
Contract module contains contract primitives used for verification of the contract data and logic [rust/redstone/rust_sdk_2/redstone/contract/index.html](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/contract/index.html)
63-
For the specific verification primitive description look in to [rust/redstone/rust_sdk_2/redstone/contract/verification](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/contract/verification/index.html)
64-
65-
## Cryptographic methods
66-
67-
1. [`redstone` crate with
68-
`crypto_secp256k1`](https://docs.redstone.finance/rust/redstone/crypto_secp256k1/redstone/index.html)
69-
pure Rust implementation
70-
2. [`redstone` crate with `crypto_secp256k1` and
71-
`network_casper`](https://docs.redstone.finance/rust/redstone/crypto_secp256k1,network_casper/redstone/index.html)
72-
extension for Casper
73-
3. [`redstone` crate with `crypto_radix` and
74-
`network_radix`](https://docs.redstone.finance/rust/redstone/crypto_radix,network_radix/redstone/index.html)
75-
extension for Radix
76-
4. Solana [rust/redstone/rust_sdk_2/redstone/solana/enum.SolanaCrypto](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/solana/enum.SolanaCrypto.html)
67+
Contract module contains contract primitives used for verification of the contract data and logic [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/contract/index.html)
68+
For the specific verification primitive description look in to [here](https://docs.redstone.finance/rust/redstone/rust_sdk_2/redstone/contract/verification/index.html)

crates/redstone/src/core/processor.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,13 @@ impl<T: RedStoneConfig> RedStonePayloadProcessor for T {
5252
}
5353

5454
fn make_processor_result<Env: Environment>(config: &Config, payload: Payload) -> ProcessorResult {
55-
let min_timestamp = payload.get_min_validated_timestamp(config)?;
55+
let timestamp = payload.get_validated_timestamp(config)?;
5656

5757
let values = aggregate_values(payload.data_packages, config)?;
5858

59-
Env::print(|| format!("{:?} {:?}", min_timestamp, values));
59+
Env::print(|| format!("{:?} {:?}", timestamp, values));
6060

61-
Ok(ValidatedPayload {
62-
values,
63-
min_timestamp,
64-
})
61+
Ok(ValidatedPayload { values, timestamp })
6562
}
6663

6764
#[cfg(feature = "helpers")]
@@ -91,19 +88,19 @@ mod tests {
9188
ETH,
9289
11,
9390
TEST_SIGNER_ADDRESS_1,
94-
(TEST_BLOCK_TIMESTAMP + 5).into(),
91+
(TEST_BLOCK_TIMESTAMP + 400).into(),
9592
),
9693
DataPackage::test_single_data_point(
9794
ETH,
9895
13,
9996
TEST_SIGNER_ADDRESS_2,
100-
(TEST_BLOCK_TIMESTAMP + 3).into(),
97+
(TEST_BLOCK_TIMESTAMP + 400).into(),
10198
),
10299
DataPackage::test_single_data_point(
103100
BTC,
104101
32,
105102
TEST_SIGNER_ADDRESS_2,
106-
(TEST_BLOCK_TIMESTAMP - 2).into(),
103+
(TEST_BLOCK_TIMESTAMP + 400).into(),
107104
),
108105
DataPackage::test_single_data_point(
109106
BTC,
@@ -121,7 +118,7 @@ mod tests {
121118
assert_eq!(
122119
result,
123120
Ok(ValidatedPayload {
124-
min_timestamp: (TEST_BLOCK_TIMESTAMP - 2).into(),
121+
timestamp: (TEST_BLOCK_TIMESTAMP + 400).into(),
125122
values: vec![12u8, 31].iter_into()
126123
})
127124
);
@@ -133,12 +130,12 @@ mod tests {
133130
DataPackage::test_multi_data_point(
134131
vec![(ETH, 10), (BTC, 31)],
135132
TEST_SIGNER_ADDRESS_2,
136-
(TEST_BLOCK_TIMESTAMP + 3).into(),
133+
(TEST_BLOCK_TIMESTAMP + 5).into(),
137134
),
138135
DataPackage::test_multi_data_point(
139136
vec![(ETH, 13), (BTC, 32)],
140137
TEST_SIGNER_ADDRESS_1,
141-
(TEST_BLOCK_TIMESTAMP + 400).into(),
138+
(TEST_BLOCK_TIMESTAMP + 5).into(),
142139
),
143140
];
144141

@@ -150,7 +147,7 @@ mod tests {
150147
assert_eq!(
151148
result,
152149
Ok(ValidatedPayload {
153-
min_timestamp: (TEST_BLOCK_TIMESTAMP + 3).into(),
150+
timestamp: (TEST_BLOCK_TIMESTAMP + 5).into(),
154151
values: vec![11u8, 31].iter_into()
155152
})
156153
);
@@ -162,22 +159,22 @@ mod tests {
162159
DataPackage::test_multi_data_point(
163160
vec![(BTC, 30), (ETH, 11)],
164161
TEST_SIGNER_ADDRESS_1,
165-
(TEST_BLOCK_TIMESTAMP + 5).into(),
162+
(TEST_BLOCK_TIMESTAMP).into(),
166163
),
167164
DataPackage::test_multi_data_point(
168165
vec![(ETH, 10), (BTC, 31)],
169166
TEST_SIGNER_ADDRESS_2,
170-
(TEST_BLOCK_TIMESTAMP + 3).into(),
167+
(TEST_BLOCK_TIMESTAMP).into(),
171168
),
172169
DataPackage::test_multi_data_point(
173170
vec![(BTC, 34), (ETH, 12)],
174171
TEST_SIGNER_ADDRESS_2, // REPETITION OF A SIGNER
175-
(TEST_BLOCK_TIMESTAMP - 2).into(),
172+
(TEST_BLOCK_TIMESTAMP).into(),
176173
),
177174
DataPackage::test_multi_data_point(
178175
vec![(ETH, 13), (BTC, 32)],
179176
TEST_SIGNER_ADDRESS_1,
180-
(TEST_BLOCK_TIMESTAMP + 400).into(),
177+
(TEST_BLOCK_TIMESTAMP).into(),
181178
),
182179
];
183180

@@ -199,12 +196,12 @@ mod tests {
199196
DataPackage::test_multi_data_point(
200197
vec![(ETH, 10), (BTC, 31), (BTC, 33)], // REPETITION IN DATAPOINTS HERE.
201198
TEST_SIGNER_ADDRESS_2,
202-
(TEST_BLOCK_TIMESTAMP + 3).into(),
199+
(TEST_BLOCK_TIMESTAMP).into(),
203200
),
204201
DataPackage::test_multi_data_point(
205202
vec![(ETH, 13), (BTC, 32)],
206203
TEST_SIGNER_ADDRESS_1,
207-
(TEST_BLOCK_TIMESTAMP + 400).into(),
204+
(TEST_BLOCK_TIMESTAMP).into(),
208205
),
209206
];
210207

crates/redstone/src/core/processor_result.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ pub type ProcessorResult = Result<ValidatedPayload, Error>;
1010
/// particularly focusing on time-sensitive data and its associated values, according to the `Config`.
1111
#[derive(Debug, Eq, PartialEq)]
1212
pub struct ValidatedPayload {
13-
/// The minimum timestamp encountered during processing.
13+
/// The timestamp encountered during processing.
1414
///
15-
/// This field captures the earliest time point (in milliseconds since the Unix epoch)
15+
/// This field captures the time point (in milliseconds since the Unix epoch)
1616
/// among the processed data packages, indicating the starting boundary of the dataset's time range.
17-
pub min_timestamp: TimestampMillis,
17+
pub timestamp: TimestampMillis,
1818

1919
/// A collection of values processed during the operation.
2020
///
@@ -25,6 +25,6 @@ pub struct ValidatedPayload {
2525

2626
impl From<ValidatedPayload> for (TimestampMillis, Vec<Value>) {
2727
fn from(validated_payload: ValidatedPayload) -> Self {
28-
(validated_payload.min_timestamp, validated_payload.values)
28+
(validated_payload.timestamp, validated_payload.values)
2929
}
3030
}

crates/redstone/src/network/error.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ pub enum Error {
108108
/// Includes FeedId that is reocuring.
109109
ConfigReocuringFeedId(FeedId),
110110

111+
/// Indicates that payload timestamps are not equal.
112+
///
113+
/// Contains the first timestamp and the one that is not equal to the first one.
114+
TimestampDifferentThanOthers(TimestampMillis, TimestampMillis),
115+
111116
/// Indicates that the provided data timestamp is not greater than a previously written package timestamp.
112117
///
113118
/// For the price adapter to accept a new price update, the associated timestamp must be
@@ -148,6 +153,7 @@ impl Error {
148153
Error::ConfigReocuringSigner(_) => 516,
149154
Error::ConfigEmptyFeedIds => 517,
150155
Error::ConfigReocuringFeedId(_) => 518,
156+
Error::TimestampDifferentThanOthers(_, _) => 519,
151157
Error::InsufficientSignerCount(data_package_index, value, _) => {
152158
(2000 + data_package_index * 10 + value) as u16
153159
}
@@ -220,6 +226,11 @@ impl Display for Error {
220226
feed_id.as_hex_str()
221227
)
222228
}
229+
Error::TimestampDifferentThanOthers(first, outstandig) => write!(
230+
f,
231+
"Timestamp {:?} is not equal to the first on {:?} in the payload.",
232+
outstandig, first
233+
),
223234
Error::DataTimestampMustBeGreaterThanBefore(current, before) => {
224235
write!(
225236
f,

0 commit comments

Comments
 (0)