Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukasz2891 committed May 24, 2023
1 parent f60c4f3 commit d468a12
Show file tree
Hide file tree
Showing 16 changed files with 1,160 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
out
target
.DS_Store
13 changes: 13 additions & 0 deletions Forc.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = 'core'
source = 'path+from-root-2C66FC65A00ECA96'

[[package]]
name = 'redstone'
source = 'member'
dependencies = ['std']

[[package]]
name = 'std'
source = 'git+https://github.com/fuellabs/sway?tag=v0.35.5#49eae2dd93a1957e2a2c2fb3f51b11eb3791fc24'
dependencies = ['core']
7 changes: 7 additions & 0 deletions Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[project]
authors = ["Łukasz Kalbarczyk"]
entry = "lib.sw"
forc-version = "0.35.0"
license = "Apache-2.0"
name = "redstone"
organization = "RedStone"
115 changes: 115 additions & 0 deletions src/aggregation.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
library aggregation;

dep utils/vec;
dep utils/numbers;

use std::{u256::U256, vec::*};
use vec::sort;
use numbers::*;

pub fn aggregate_results(results: Vec<Vec<U256>>) -> Vec<U256> {
let mut aggregated = Vec::new();

let mut i = 0;
while (i < results.len) {
let values = results.get(i).unwrap();
aggregated.push(aggregate_values(values));

i += 1;
}

return aggregated;
}

fn aggregate_values(values: Vec<U256>) -> U256 {
let mut values = values;
sort(values);
let mut j = 0;
while (j < values.len) {
j += 1;
}

let mid = values.len / 2;

if (values.len - 2 * mid == 1) {
return values.get(mid).unwrap();
}

return (values.get(mid).unwrap() + values.get(mid - 1).unwrap()).rsh(1);
}

#[test]
fn test_aggregate_single_value() {
let mut data = Vec::new();
data.push(U256::from_u64(333));

let aggregated = aggregate_values(data);
assert(aggregated == U256::from_u64(333));
}

#[test]
fn test_aggregate_two_values() {
let mut data = Vec::new();
data.push(U256::from_u64(333));
data.push(U256::from_u64(222));

let aggregated = aggregate_values(data);
assert(aggregated == U256::from_u64(277));
}

#[test]
fn test_aggregate_three_values() {
let mut data = Vec::new();

data.push(U256::from_u64(444));
data.push(U256::from_u64(222));
data.push(U256::from_u64(333));

let aggregated = aggregate_values(data);
assert(aggregated == U256::from_u64(333));
}

#[test]
fn test_aggregate_four_values() {
let mut data = Vec::new();

data.push(U256::from_u64(444));
data.push(U256::from_u64(222));
data.push(U256::from_u64(111));
data.push(U256::from_u64(555));

let aggregated = aggregate_values(data);
assert(aggregated == U256::from_u64(333));
}

#[test]
fn test_aggregate_five_values() {
let mut data = Vec::new();

data.push(U256::from_u64(444));
data.push(U256::from_u64(222));
data.push(U256::from_u64(111));
data.push(U256::from_u64(333));
data.push(U256::from_u64(555));

let aggregated = aggregate_values(data);
assert(aggregated == U256::from_u64(333));
}

#[test]
fn test_aggregate_three_other_values() {
let mut data = Vec::new();

data.push(U256::from_u64(222));
data.push(U256::from_u64(222));
data.push(U256::from_u64(333));

let aggregated = aggregate_values(data);
assert(aggregated == U256::from_u64(222));
}

#[test(should_revert)]
fn test_aggregate_zero_values() {
let data = Vec::new();
aggregate_values(data);
}
31 changes: 31 additions & 0 deletions src/config.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
library config;

dep utils/vec;

use std::{option::*, u256::U256};
use vec::{value_index, value_index_b256};

pub struct Config {
signers: Vec<b256>,
feed_ids: Vec<U256>,
signer_count_threshold: u64,
block_timestamp: u64, // unix
}

impl Config {
pub fn cap(self) -> u64 {
return self.signers.len * self.feed_ids.len;
}

pub fn signer_index(self, signer: b256) -> Option<u64> {
return value_index_b256(self.signers, signer);
}

pub fn feed_id_index(self, feed_id: U256) -> Option<u64> {
return value_index(self.feed_ids, feed_id);
}

pub fn index(self, feed_id_index: u64, signer_index: u64) -> u64 {
return self.signers.len * feed_id_index + signer_index
}
}
124 changes: 124 additions & 0 deletions src/config_validation.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
library config_validation;

dep protocol;
dep config;
dep validation;
dep utils/numbers;

use std::u256::U256;
use protocol::{DataPackage, Payload};
use config::Config;
use validation::*;
use numbers::*;

/// 655360000 + feed_index
pub const INSUFFICIENT_SIGNER_COUNT = 0x2710_0000;

/// 1310720000 + data_package_index
pub const SIGNER_NOT_RECOGNIZED = 0x4e20_0000;

trait Validation {
fn validate_timestamps(self, payload: Payload);
fn validate_signer_count(self, values: Vec<Vec<U256>>);
fn validate_signer(self, data_package: DataPackage, index: u64) -> Option<u64>;
}

impl Validation for Config {
fn validate_timestamps(self, payload: Payload) {
let mut i = 0;
while (i < payload.data_packages.len) {
let timestamp = payload.data_packages.get(i).unwrap().timestamp / 1000;
let block_timestamp = self.block_timestamp;

validate_timestamp(i, timestamp, block_timestamp);

i += 1;
}
}

fn validate_signer_count(self, results: Vec<Vec<U256>>) {
let mut i = 0;
while (i < self.feed_ids.len) {
let values = results.get(i).unwrap();
if (values.len < self.signer_count_threshold) {
log(values.len);
revert(INSUFFICIENT_SIGNER_COUNT + i);
}

i += 1;
}
}

fn validate_signer(self, data_package: DataPackage, index: u64) -> Option<u64> {
let s = self.signer_index(data_package.signer_address.value);

if s.is_none() {
log(data_package.signer_address.value);
// revert(SIGNER_NOT_RECOGNIZED + index);
}

return s;
}
}

fn make_results() -> Vec<Vec<U256>> {
let mut results = Vec::new();

let mut set1 = Vec::new();
set1.push(U256::from_u64(111));
set1.push(U256::from_u64(777));

let mut set2 = Vec::new();
set2.push(U256::from_u64(444));
set2.push(U256::from_u64(555));
set2.push(U256::from_u64(666));

let mut set3 = Vec::new();
set3.push(U256::from_u64(222));
set3.push(U256::from_u64(333));

results.push(set1);
results.push(set2);
results.push(set3);

return results;
}

fn make_config(signer_count_threshold: u64) -> Config {
let mut feed_ids = Vec::new();
feed_ids.push(U256::from_u64(0x444444));
feed_ids.push(U256::from_u64(0x445566));
feed_ids.push(U256::from_u64(0x556644));

let config = Config {
feed_ids: feed_ids,
signers: Vec::new(),
signer_count_threshold,
block_timestamp: 0,
};

return config;
}
#[test]
fn test_validate_one_signer() {
let results = make_results();
let config = make_config(1);

config.validate_signer_count(results);
}

#[test]
fn test_validate_two_signers() {
let results = make_results();
let config = make_config(2);

config.validate_signer_count(results);
}

#[test(should_revert)]
fn test_validate_three_signers() {
let results = make_results();
let config = make_config(3);

config.validate_signer_count(results);
}
67 changes: 67 additions & 0 deletions src/crypto.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
library crypto;

dep utils/bytes;
dep sample;

use std::{
b256::*,
b512::*,
bytes::*,
ecr::{
ec_recover,
EcRecoverError,
},
hash::keccak256,
logging::log,
vm::evm::ecr::ec_recover_evm_address,
vm::evm::evm_address::EvmAddress,
};
use bytes::*;
use sample::{SAMPLE_ID_V27, SAMPLE_ID_V28, SampleDataPackage};

pub fn recover_signer_address(signature_bytes: Bytes, signable_bytes: Bytes) -> EvmAddress {
let (r_bytes, mut s_bytes) = signature_bytes.slice_tail_offset(32, 1);
let v = signature_bytes.get(signature_bytes.len - 1).unwrap();
let r_number = b256::try_from(r_bytes).unwrap();
let s_number = b256::try_from(s_bytes).unwrap();

let hash = signable_bytes.keccak256();

return recover_public_address(r_number, s_number, v, hash).unwrap();
}

fn recover_public_address(
r: b256,
s: b256,
v: u64,
msg_hash: b256,
) -> Result<EvmAddress, EcRecoverError> {
let mut v_256: b256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
if (v == 28) {
v_256 = 0x0000000000000000000000000000000000000000000000000000000000000001;
}

let mut s_with_parity = s | (v_256 << 255);

let signature = B512 {
bytes: [r, s_with_parity],
};

return ec_recover_evm_address(signature, msg_hash);
}

#[test]
fn test_recover_signer_address_v27() {
let sample = SampleDataPackage::sample(SAMPLE_ID_V27);
let result = recover_signer_address(sample.signature_bytes(), sample.signable_bytes);

assert(sample.signer_address == result.value);
}

#[test]
fn test_recover_signer_address_v28() {
let sample = SampleDataPackage::sample(SAMPLE_ID_V28);
let result = recover_signer_address(sample.signature_bytes(), sample.signable_bytes);

assert(sample.signer_address == result.value);
}
6 changes: 6 additions & 0 deletions src/lib.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
library redstone;

dep config;
dep crypto;
dep processor;
dep protocol;
Loading

0 comments on commit d468a12

Please sign in to comment.