mirror of
https://github.com/fluencelabs/eip712-validation-node
synced 2025-05-06 05:22:15 +00:00
120 lines
3.7 KiB
Rust
120 lines
3.7 KiB
Rust
/*
|
|
* Copyright 2021 Fluence Labs Limited
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
use marine_rs_sdk::marine;
|
|
use marine_rs_sdk::module_manifest;
|
|
use marine_rs_sdk::WasmLoggerBuilder;
|
|
|
|
module_manifest!();
|
|
|
|
pub fn main() {
|
|
WasmLoggerBuilder::new().build().unwrap();
|
|
}
|
|
|
|
#[marine]
|
|
#[derive(Default, Debug)]
|
|
pub struct Consensus {
|
|
pub n: u64,
|
|
pub threshold: f64,
|
|
pub valid: u64,
|
|
pub invalid: u64,
|
|
pub consensus: bool,
|
|
}
|
|
|
|
#[marine]
|
|
#[derive(Default, Debug)]
|
|
pub struct CResult {
|
|
pub stderr: String,
|
|
pub stdout: Vec<Consensus>, // always length 0 or 1
|
|
}
|
|
|
|
impl CResult {
|
|
pub fn new(err: Option<String>, out: Option<Consensus>) -> Self {
|
|
match out {
|
|
Some(out) => CResult {
|
|
stderr: "".to_string(),
|
|
stdout: vec![out],
|
|
},
|
|
None => match err {
|
|
Some(e) => CResult {
|
|
stderr: e,
|
|
stdout: Vec::new(),
|
|
},
|
|
None => CResult {
|
|
stderr: "failure to procure error".to_string(),
|
|
stdout: Vec::new(),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
#[marine]
|
|
pub fn consensus(payload: Vec<bool>, threshold: f64) -> CResult {
|
|
if payload.len() == 0 {
|
|
return CResult::new(Some("no records provided".to_string()), None);
|
|
}
|
|
if threshold < 0.0 || threshold > 1.0 {
|
|
return CResult::new(Some("invalid threshold value".to_string()), None);
|
|
}
|
|
let valids: u64 = payload.iter().filter(|&b| *b == true).count() as u64;
|
|
let invalids: u64 = payload.iter().filter(|&b| *b == false).count() as u64;
|
|
let c_ratio: f64 = valids as f64 / payload.len() as f64;
|
|
let mut cons: bool = false;
|
|
if c_ratio >= threshold {
|
|
cons = true;
|
|
}
|
|
let c = Consensus {
|
|
n: payload.len() as u64,
|
|
threshold,
|
|
valid: valids,
|
|
invalid: invalids,
|
|
consensus: cons,
|
|
};
|
|
CResult::new(None, Some(c))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use marine_rs_sdk_test::marine_test;
|
|
#[marine_test(config_path = "../Config.toml", modules_dir = "../artifacts")]
|
|
fn test_consensus(consensus: marine_test_env::consensus::ModuleInterface) {
|
|
let data_1 = vec![true, true, true, false, false];
|
|
let data_2 = vec![true, true, false, false, false];
|
|
let threshold_1: f64 = 0.6f64;
|
|
let threshold_bad: f64 = 1.6f64;
|
|
|
|
let c_true = consensus.consensus(data_1.clone(), threshold_1.clone());
|
|
println!("{:?}", c_true);
|
|
println!("{:?}", c_true.stdout[0].consensus);
|
|
|
|
assert!(c_true.stdout[0].consensus);
|
|
assert_eq!(c_true.stderr.len(), 0);
|
|
assert_eq!(c_true.stdout[0].n, data_1.len() as u64);
|
|
assert_eq!(c_true.stdout[0].valid, 3u64);
|
|
assert_eq!(c_true.stdout[0].invalid, 2u64);
|
|
|
|
let c_false = consensus.consensus(data_2.clone(), threshold_1.clone());
|
|
assert!(!c_false.stdout[0].consensus);
|
|
assert_eq!(c_false.stdout[0].valid, 2u64);
|
|
assert_eq!(c_false.stdout[0].invalid, 3u64);
|
|
|
|
let c_bad = consensus.consensus(data_2, threshold_bad);
|
|
assert_eq!(c_bad.stderr.len(), 23usize);
|
|
assert_eq!(c_bad.stdout.len(), 0usize);
|
|
}
|
|
}
|