2 个版本
使用旧的 Rust 2015
0.1.1 | 2016年6月10日 |
---|---|
0.1.0 | 2016年6月10日 |
#33 在 #verifiable
230KB
714 行
data_chain
数据块通过链接提供加密可验证的保证,证明它们包含网络有效数据,并且之前已被安全网络接受。
[API 文档] (https://dirvine.github.io/data_chain/master/data_chain/)
[RFC] (https://github.com/dirvine/data_chain/blob/master/docs/0029-data-blocks.md)
lib.rs
:
#data_chain 数据块可以链接起来,提供可验证的保证,证明它们包含网络有效数据且未被注入。
链可能看起来像
`link` - all current group members - cryptographically secured as valid
data - DataIdentifiers interspersed in a chain of links
data - each block signed by a majority of previous link
....
`link` - As churn events occur new links are created
`link` - each link will have a majority
(usually n - 1 actually) members of previous link
当链呈现给当前紧密组(最后链接中识别的组)时,可以验证它持有数据,这些数据是在网络中经过时间验证存在的,链提供数据组和组成员资格随时间变化的加密证明。
链接是群组协议链组件,通过排序网络节点(地址)最近的节点并发送此签名哈希到该节点来创建。接收者将接收这些,NodeBlocks
并创建链链接。此链接将允许群组同意的成员为此链签名 DataBlocks
。如果链接成员的大多数签署了数据,则数据有效地在链中。在组成员资格变更时,链中构建一个新的链接,并重复此过程。链可以分裂,节点将维护多个链,这取决于与链链接的数据重叠。链接标识符是包含当前节点的所有群组成员的哈希。
链链接容器也可能会在组中维护,以证明网络的历史成员资格。这个动作的有效性还没有被充分理解,但它在网络重新启动的事件中可能很有价值。请参阅[github 仓库][1]和[RFC][3]。
示例
基本用法
extern crate sodiumoxide;
extern crate data_chain;
extern crate itertools;
fn main() {
use sodiumoxide::crypto;
use sodiumoxide::crypto::hash::sha256;
use itertools::Itertools;
use data_chain::{NodeBlock, BlockIdentifier, DataChain, create_link_descriptor};
::sodiumoxide::init();
let keys = (0..50)
.map(|_| crypto::sign::gen_keypair())
.collect_vec();
// ########################################################################################
// create groups of keys to resemble close_groups
// ########################################################################################
let pub1 = keys.iter().map(|x| x.0).take(3).collect_vec();
let pub2 = keys.iter().map(|x| x.0).skip(1).take(3).collect_vec();
let pub3 = keys.iter().map(|x| x.0).skip(2).take(3).collect_vec();
assert!(pub1 != pub2);
assert!(pub1 != pub3);
assert!(pub1.len() == 3);
assert!(pub2.len() == 3);
assert!(pub3.len() == 3);
let link_desc1 = create_link_descriptor(&pub1[..]);
let identifier1 = BlockIdentifier::Link(link_desc1);
let id_ident = BlockIdentifier::ImmutableData(sha256::hash(b"id1hash"));
let sd1_ident = BlockIdentifier::StructuredData(sha256::hash(b"sd1hash"),
sha256::hash(b"sd1name"));
let sd2_ident = BlockIdentifier::StructuredData(sha256::hash(b"s21hash"),
sha256::hash(b"sd2name"));
assert!(identifier1 != id_ident);
assert!(identifier1 != sd1_ident);
assert!(id_ident != sd1_ident);
assert!(sd1_ident != sd2_ident);
// ########################################################################################
// Create NodeBlocks, these are what nodes send to each other
// Here they are all links only. For Put Delete Post
// these would be Identifiers for the data types that includes a hash of the serialised data
// ########################################################################################
let link1_1 = NodeBlock::new(&keys[0].0, &keys[0].1, identifier1.clone());
let link1_2 = NodeBlock::new(&keys[1].0, &keys[1].1, identifier1.clone());
let link1_3 = NodeBlock::new(&keys[2].0, &keys[2].1, identifier1);
let sd1_1 = NodeBlock::new(&keys[1].0, &keys[1].1, id_ident.clone());
// here we need to add 2_1 again as 2_1 will be purged as part of test later on
let sd1_1_again_1 = NodeBlock::new(&keys[1].0, &keys[1].1, id_ident.clone());
let sd1_1_again_2 = NodeBlock::new(&keys[1].0, &keys[1].1, id_ident.clone());
let sd1_2 = NodeBlock::new(&keys[2].0, &keys[2].1, id_ident.clone());
let sd1_3 = NodeBlock::new(&keys[3].0, &keys[3].1, id_ident);
let id_1 = NodeBlock::new(&keys[2].0, &keys[2].1, sd1_ident.clone());
let id_2 = NodeBlock::new(&keys[3].0, &keys[3].1, sd1_ident.clone()); // fail w/wrong keys
let id_3 = NodeBlock::new(&keys[4].0, &keys[4].1, sd1_ident); // fail w/wrong keys
// #################### Create chain ########################
let mut chain = DataChain::default();
assert!(chain.is_empty());
// ############# start adding link #####################
assert!(chain.add_node_block(link1_1.unwrap()).is_none());
assert!(chain.validate_ownership(&pub1)); // 1 link - all OK
assert_eq!(chain.len(), 1);
assert!(chain.add_node_block(link1_2.unwrap()).is_none());
assert!(chain.validate_ownership(&pub1)); // 1 link - all OK
assert_eq!(chain.len(), 1);
assert!(chain.add_node_block(link1_3.unwrap()).is_none());
assert!(chain.validate_ownership(&pub1)); // 1 link - all OK
assert_eq!(chain.len(), 1);
// ########################################################################################
// pune_and_validate will prune any invalid data, In first link all data is valid if sig OK
// ########################################################################################
assert!(chain.validate_ownership(&pub1));
assert!(!chain.validate_ownership(&pub3));
assert_eq!(chain.len(), 1);
assert_eq!(chain.blocks_len(), 0);
assert_eq!(chain.links_len(), 1);
assert!(chain.add_node_block(sd1_1.unwrap()).is_none());
// ########################################################################################
// Ading a link block will not increase length of chain links as it's not yet valid
// ########################################################################################
assert_eq!(chain.links_len(), 1);
assert_eq!(chain.len(), 2); // contains an invalid link for now
assert_eq!(chain.valid_len(), 1);
assert!(chain.add_node_block(sd1_1_again_1.unwrap()).is_none()); // re-add 2.1
// ########################################################################################
// The call below will prune 2_1 as it is a new link without majority agreement
// ########################################################################################
assert!(chain.validate_ownership(&pub2));
assert_eq!(chain.links_len(), 1);
assert!(chain.add_node_block(sd1_1_again_2.unwrap()).is_none()); // re-add 2.1
assert!(chain.add_node_block(sd1_2.unwrap()).is_some()); // majority reached here
assert!(chain.validate_ownership(&pub2)); // Ok as now 2 is in majority
assert_eq!(chain.links_len(), 1);
assert_eq!(chain.blocks_len(), 1);
assert_eq!(chain.len(), 2);
assert!(chain.add_node_block(sd1_3.unwrap()).is_some());
assert!(chain.validate_ownership(&pub2));
assert_eq!(chain.links_len(), 1);
assert_eq!(chain.blocks_len(), 1);
assert_eq!(chain.len(), 2);
// the call below will not add any links
let id1 = id_1.unwrap();
assert!(chain.add_node_block(id1.clone()).is_none()); // only 1st id has valid signature
assert!(chain.add_node_block(id_3.unwrap()).is_none()); // will not get majority
assert!(chain.add_node_block(id_2.unwrap()).is_none());
assert_eq!(chain.links_len(), 1);
assert_eq!(chain.blocks_len(), 1);
assert_eq!(chain.len(), 3);
chain.prune();
assert_eq!(chain.len(), 2);
assert_eq!(chain.valid_len(), 2);
assert!(chain.add_node_block(id1.clone()).is_none());
assert_eq!(chain.len(), 3);
assert_eq!(chain.valid_len(), 2);
chain.remove(id1.identifier());
assert_eq!(chain.len(), 2);
assert!(chain.add_node_block(id1.clone()).is_none());
assert_eq!(chain.len(), 3);
assert_eq!(chain.valid_len(), 2);
}
恐慌
错误
安全性
中止
此软件包中没有中止。
未定义行为
未知的。[1]: https://github.com/dirvine/data_chain/tree/master [3]: https://github.com/dirvine/data_chain/blob/master/docs/0029-data-blocks.md
依赖关系
~29MB
~341K SLoC