#chain #networking #link #valid #verifiable #blocks #node

data_chain

在去中心化网络上安全记录数据的方法

2 个版本

使用旧的 Rust 2015

0.1.1 2016年6月10日
0.1.0 2016年6月10日

#33#verifiable

GPL-3.0 许可证

230KB
714

data_chain

数据块通过链接提供加密可验证的保证,证明它们包含网络有效数据,并且之前已被安全网络接受。

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)

Build Status


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