Skip to content
Snippets Groups Projects
Select Git revision
  • 4712f89f526b0e46089f3c702da0b0439df6e63d
  • main default protected
  • release/1.1
  • encrypt_comments
  • mnemonic_dewif
  • authors_rules
  • 0.14
  • rtd
  • 1.2.1 protected
  • 1.2.0 protected
  • 1.1.1 protected
  • 1.1.0 protected
  • 1.0.0 protected
  • 1.0.0rc1 protected
  • 1.0.0rc0 protected
  • 1.0.0-rc protected
  • 0.62.0 protected
  • 0.61.0 protected
  • 0.60.1 protected
  • 0.58.1 protected
  • 0.60.0 protected
  • 0.58.0 protected
  • 0.57.0 protected
  • 0.56.0 protected
  • 0.55.1 protected
  • 0.55.0 protected
  • 0.54.3 protected
  • 0.54.2 protected
28 results

config

Blame
  • parser.rs 15.61 KiB
    //  Copyright (C) 2017-2019  The AXIOM TEAM Association.
    //
    // This program is free software: you can redistribute it and/or modify
    // it under the terms of the GNU Affero General Public License as
    // published by the Free Software Foundation, either version 3 of the
    // License, or (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU Affero General Public License for more details.
    //
    // You should have received a copy of the GNU Affero General Public License
    // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    
    //! Parsers for block.
    
    use crate::block::{BlockDocument, BlockDocumentV10};
    use dubp_common_doc::{BlockHash, BlockNumber};
    use dubp_currency_params::genesis_block_params::v10::BlockV10Parameters;
    use dubp_currency_params::CurrencyName;
    use dubp_user_docs::documents::membership::v10::MembershipType;
    use dubp_user_docs::documents::transaction::TransactionDocument;
    use dubp_user_docs::parsers::{serde_json_value_to_pest_json_value, DefaultHasher};
    use dup_crypto::bases::BaseConvertionError;
    use dup_crypto::hashs::Hash;
    use dup_crypto::keys::*;
    use failure::Error;
    use json_pest_parser::*;
    use std::str::FromStr;
    
    pub fn parse_json_block_from_serde_value(
        serde_json_value: &serde_json::Value,
    ) -> Result<BlockDocument, Error> {
        parse_json_block(&serde_json_value_to_pest_json_value(serde_json_value)?)
    }
    
    pub fn parse_json_block(json_block: &JSONValue<DefaultHasher>) -> Result<BlockDocument, Error> {
        if !json_block.is_object() {
            return Err(ParseJsonError {
                cause: "Json block must be an object !".to_owned(),
            }
            .into());
        }
    
        let json_block = json_block.to_object().expect("safe unwrap");
    
        let currency = get_str(json_block, "currency")?;
    
        let block_number = get_number(json_block, "number")?.trunc() as u32;
    
        Ok(BlockDocument::V10(BlockDocumentV10 {
            version: get_number(json_block, "version")?.trunc() as u32,
            nonce: get_u64(json_block, "nonce")?,
            number: BlockNumber(block_number),
            pow_min: get_number(json_block, "powMin")?.trunc() as usize,
            time: get_number(json_block, "time")?.trunc() as u64,
            median_time: get_number(json_block, "medianTime")?.trunc() as u64,
            members_count: get_number(json_block, "membersCount")?.trunc() as usize,
            monetary_mass: get_number(json_block, "monetaryMass")
                .unwrap_or(0f64)
                .trunc() as usize,
            unit_base: get_number(json_block, "unitbase")?.trunc() as usize,
            issuers_count: get_number(json_block, "issuersCount")?.trunc() as usize,
            issuers_frame: get_number(json_block, "issuersFrame")?.trunc() as usize,
            issuers_frame_var: get_number(json_block, "issuersFrameVar")?.trunc() as isize,
            currency: CurrencyName(currency.to_owned()),
            issuers: vec![PubKey::Ed25519(ed25519::PublicKey::from_base58(get_str(
                json_block, "issuer",
            )?)?)],
            signatures: vec![Sig::Ed25519(ed25519::Signature::from_base64(get_str(
                json_block,
                "signature",
            )?)?)],
            hash: Some(BlockHash(Hash::from_hex(get_str(json_block, "hash")?)?)),
            parameters: get_optional_str_not_empty(json_block, "parameters")?
                .map(BlockV10Parameters::from_str)
                .transpose()?,
            previous_hash: if block_number == 0 {
                None
            } else {
                Some(Hash::from_hex(get_str(json_block, "previousHash")?)?)
            },
            previous_issuer: if block_number == 0 {
                None
            } else {
                Some(PubKey::Ed25519(ed25519::PublicKey::from_base58(get_str(
                    json_block,
                    "previousIssuer",
                )?)?))
            },
            inner_hash: Some(Hash::from_hex(get_str(json_block, "inner_hash")?)?),
            dividend: get_optional_usize(json_block, "dividend")?,
            identities: dubp_user_docs::parsers::identities::parse_compact_identities(
                currency,
                get_str_array(json_block, "identities")?,
            )?,
            joiners: dubp_user_docs::parsers::memberships::parse_compact_memberships(
                currency,
                MembershipType::In(),
                &get_str_array(json_block, "joiners")?,
            )?,
            actives: dubp_user_docs::parsers::memberships::parse_compact_memberships(
                currency,
                MembershipType::In(),
                &get_str_array(json_block, "actives")?,
            )?,
            leavers: dubp_user_docs::parsers::memberships::parse_compact_memberships(
                currency,
                MembershipType::Out(),
                &get_str_array(json_block, "leavers")?,
            )?,
            revoked: dubp_user_docs::parsers::revoked::parse_revocations_into_compact(&get_str_array(
                json_block, "revoked",
            )?),
            excluded: get_str_array(json_block, "excluded")?
                .iter()
                .map(|p| ed25519::PublicKey::from_base58(p))
                .map(|p| p.map(PubKey::Ed25519))
                .collect::<Result<Vec<PubKey>, BaseConvertionError>>()?,
            certifications: dubp_user_docs::parsers::certifications::parse_certifications_into_compact(
                &get_str_array(json_block, "certifications")?,
            ),
            transactions: json_block
                .get("transactions")
                .ok_or_else(|| ParseJsonError {
                    cause: "Fail to parse json block : field 'transactions' must exist !".to_owned(),
                })?
                .to_array()
                .ok_or_else(|| ParseJsonError {
                    cause: "Fail to parse json block : field 'transactions' must be an array !"
                        .to_owned(),
                })?
                .iter()
                .map(|tx| dubp_user_docs::parsers::transactions::parse_json_transaction(tx))
                .collect::<Result<Vec<TransactionDocument>, Error>>()?,
        }))
    }
    
    #[cfg(test)]
    mod tests {
        use super::*;
        use crate::block::*;
    
        #[test]
        fn parse_empty_json_block() {
            let block_json_str = r#"{
       "version": 10,
       "nonce": 10200000037108,
       "number": 7,
       "powMin": 70,
       "time": 1488987677,
       "medianTime": 1488987394,
       "membersCount": 59,
       "monetaryMass": 59000,
       "unitbase": 0,
       "issuersCount": 1,
       "issuersFrame": 6,
       "issuersFrameVar": 0,
       "currency": "g1",
       "issuer": "2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ",
       "signature": "xaWNjdFeE4yr9+AKckgR6QuAvMzmKUWfY+uIlC3HKjn2apJqG70Gf59A71W+Ucz6E9WPXRzDDF/xOrf6GCGHCA==",
       "hash": "0000407900D981FC17B5A6FBCF8E8AFA4C00FAD7AFC5BEA9A96FF505E5D105EC",
       "parameters": "",
       "previousHash": "0000379BBE6ABC18DCFD6E4733F9F76CB06593D10FAEDF722BE190C277AC16EA",
       "previousIssuer": "2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ",
       "inner_hash": "CF2701092D5A34A55802E343B5F8D61D9B7E8089F1F13A19721234DF5B2F0F38",
       "dividend": null,
       "identities": [],
       "joiners": [],
       "actives": [],
       "leavers": [],
       "revoked": [],
       "excluded": [],
       "certifications": [],
       "transactions": [],
       "raw": "Version: 10\nType: Block\nCurrency: g1\nNumber: 7\nPoWMin: 70\nTime: 1488987677\nMedianTime: 1488987394\nUnitBase: 0\nIssuer: 2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ\nIssuersFrame: 6\nIssuersFrameVar: 0\nDifferentIssuersCount: 1\nPreviousHash: 0000379BBE6ABC18DCFD6E4733F9F76CB06593D10FAEDF722BE190C277AC16EA\nPreviousIssuer: 2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ\nMembersCount: 59\nIdentities:\nJoiners:\nActives:\nLeavers:\nRevoked:\nExcluded:\nCertifications:\nTransactions:\nInnerHash: CF2701092D5A34A55802E343B5F8D61D9B7E8089F1F13A19721234DF5B2F0F38\nNonce: 10200000037108\n"
      }"#;
    
            let block_json_value = json_pest_parser::parse_json_string(block_json_str)
                .expect("Fail to parse json block !");
            assert_eq!(
                BlockDocument::V10(BlockDocumentV10 {
                    version: 10,
                    nonce: 10200000037108,
                    number: BlockNumber(7),
                    pow_min: 70,
                    time: 1488987677,
                    median_time: 1488987394,
                    members_count: 59,
                    monetary_mass: 59000,
                    unit_base: 0,
                    issuers_count: 1,
                    issuers_frame: 6,
                    issuers_frame_var: 0,
                    currency: CurrencyName("g1".to_owned()),
                    issuers: vec![PubKey::Ed25519(
                        ed25519::PublicKey::from_base58("2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ")
                            .expect("Fail to parse issuer !")
                    )],
                    signatures: vec![Sig::Ed25519(
                        ed25519::Signature::from_base64("xaWNjdFeE4yr9+AKckgR6QuAvMzmKUWfY+uIlC3HKjn2apJqG70Gf59A71W+Ucz6E9WPXRzDDF/xOrf6GCGHCA==").expect("Fail to parse sig !")
                    )],
                    hash: Some(BlockHash(
                        Hash::from_hex(
                            "0000407900D981FC17B5A6FBCF8E8AFA4C00FAD7AFC5BEA9A96FF505E5D105EC"
                        )
                        .expect("Fail to parse hash !")
                    )),
                    parameters: None,
                    previous_hash: Some(Hash::from_hex(
                        "0000379BBE6ABC18DCFD6E4733F9F76CB06593D10FAEDF722BE190C277AC16EA"
                    )
                    .expect("Fail to parse previous_hash !")),
                    previous_issuer: Some(PubKey::Ed25519(
                        ed25519::PublicKey::from_base58("2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ")
                            .expect("Fail to parse previous issuer !")
                    )),
                    inner_hash: Some(
                        Hash::from_hex(
                            "CF2701092D5A34A55802E343B5F8D61D9B7E8089F1F13A19721234DF5B2F0F38"
                        )
                        .expect("Fail to parse inner hash !")
                    ),
                    dividend: None,
                    identities: vec![],
                    joiners: vec![],
                    actives: vec![],
                    leavers: vec![],
                    revoked: vec![],
                    excluded: vec![],
                    certifications: vec![],
                    transactions: vec![],
                }),
                parse_json_block(&block_json_value).expect("Fail to parse block_json_value !")
            );
        }
    
        #[test]
        fn parse_json_block_with_one_tx() -> Result<(), VerifyBlockHashError> {
            let block_json_str = r#"{
       "version": 10,
       "nonce": 10100000033688,
       "number": 52,
       "powMin": 74,
       "time": 1488990898,
       "medianTime": 1488990117,
       "membersCount": 59,
       "monetaryMass": 59000,
       "unitbase": 0,
       "issuersCount": 1,
       "issuersFrame": 6,
       "issuersFrameVar": 0,
       "currency": "g1",
       "issuer": "2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ",
       "signature": "4/UIwXzWQekbYw7fpD8ueMH4GnDEwCM+DvDaTfquBXOvFXLRYo/S+Vrk5u7so/98gYaZ2O7Myh20xgQvhh5FDQ==",
       "hash": "000057D4B29AF6DADB16F841F19C54C00EB244CECA9C8F2D4839D54E5F91451C",
       "parameters": "",
       "previousHash": "00000FEDA61240DD125A26886FEB2E6995B52A94778C71224CAF8492FF257D47",
       "previousIssuer": "2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ",
       "inner_hash": "6B27ACDA51F416449E5A61FC69438F8974D11FC27EB7A992410C276FC0B9BA5F",
       "dividend": null,
       "identities": [],
       "joiners": [],
       "actives": [],
       "leavers": [],
       "revoked": [],
       "excluded": [],
       "certifications": [],
       "transactions": [
        {
         "version": 10,
         "currency": "g1",
         "locktime": 0,
         "blockstamp": "50-00001DAA4559FEDB8320D1040B0F22B631459F36F237A0D9BC1EB923C12A12E7",
         "blockstampTime": 1488990016,
         "issuers": [
          "2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ"
         ],
         "inputs": [
          "1000:0:D:2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ:1"
         ],
         "outputs": [
          "1:0:SIG(Com8rJukCozHZyFao6AheSsfDQdPApxQRnz7QYFf64mm)",
          "999:0:SIG(2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ)"
         ],
         "unlocks": [
          "0:SIG(0)"
         ],
         "signatures": [
          "fAH5Gor+8MtFzQZ++JaJO6U8JJ6+rkqKtPrRr/iufh3MYkoDGxmjzj6jCADQL+hkWBt8y8QzlgRkz0ixBcKHBw=="
         ],
         "comment": "TEST",
         "block_number": 0,
         "time": 0
        }
       ],
       "raw": "Version: 10\nType: Block\nCurrency: g1\nNumber: 52\nPoWMin: 74\nTime: 1488990898\nMedianTime: 1488990117\nUnitBase: 0\nIssuer: 2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ\nIssuersFrame: 6\nIssuersFrameVar: 0\nDifferentIssuersCount: 1\nPreviousHash: 00000FEDA61240DD125A26886FEB2E6995B52A94778C71224CAF8492FF257D47\nPreviousIssuer: 2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ\nMembersCount: 59\nIdentities:\nJoiners:\nActives:\nLeavers:\nRevoked:\nExcluded:\nCertifications:\nTransactions:\nTX:10:1:1:1:2:1:0\n50-00001DAA4559FEDB8320D1040B0F22B631459F36F237A0D9BC1EB923C12A12E7\n2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ\n1000:0:D:2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ:1\n0:SIG(0)\n1:0:SIG(Com8rJukCozHZyFao6AheSsfDQdPApxQRnz7QYFf64mm)\n999:0:SIG(2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ)\nTEST\nfAH5Gor+8MtFzQZ++JaJO6U8JJ6+rkqKtPrRr/iufh3MYkoDGxmjzj6jCADQL+hkWBt8y8QzlgRkz0ixBcKHBw==\nInnerHash: 6B27ACDA51F416449E5A61FC69438F8974D11FC27EB7A992410C276FC0B9BA5F\nNonce: 10100000033688\n"
      }"#;
    
            let block_json_value = json_pest_parser::parse_json_string(block_json_str)
                .expect("Fail to parse json block !");
    
            let expected_block = BlockDocument::V10(BlockDocumentV10 {
                    version: 10,
                    nonce: 10100000033688,
                    number: BlockNumber(52),
                    pow_min: 74,
                    time: 1488990898,
                    median_time: 1488990117,
                    members_count: 59,
                    monetary_mass: 59000,
                    unit_base: 0,
                    issuers_count: 1,
                    issuers_frame: 6,
                    issuers_frame_var: 0,
                    currency: CurrencyName("g1".to_owned()),
                    issuers: vec![PubKey::Ed25519(
                        ed25519::PublicKey::from_base58("2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ")
                            .expect("Fail to parse issuer !")
                    )],
                    signatures: vec![Sig::Ed25519(
                        ed25519::Signature::from_base64("4/UIwXzWQekbYw7fpD8ueMH4GnDEwCM+DvDaTfquBXOvFXLRYo/S+Vrk5u7so/98gYaZ2O7Myh20xgQvhh5FDQ==").expect("Fail to parse sig !")
                    )],
                    hash: Some(BlockHash(
                        Hash::from_hex(
                            "000057D4B29AF6DADB16F841F19C54C00EB244CECA9C8F2D4839D54E5F91451C"
                        )
                        .expect("Fail to parse hash !")
                    )),
                    parameters: None,
                    previous_hash: Some(Hash::from_hex(
                        "00000FEDA61240DD125A26886FEB2E6995B52A94778C71224CAF8492FF257D47"
                    )
                    .expect("Fail to parse previous_hash !")),
                    previous_issuer: Some(PubKey::Ed25519(
                        ed25519::PublicKey::from_base58("2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ")
                            .expect("Fail to parse previous issuer !")
                    )),
                    inner_hash: Some(
                        Hash::from_hex(
                            "6B27ACDA51F416449E5A61FC69438F8974D11FC27EB7A992410C276FC0B9BA5F"
                        )
                        .expect("Fail to parse inner hash !")
                    ),
                    dividend: None,
                    identities: vec![],
                    joiners: vec![],
                    actives: vec![],
                    leavers: vec![],
                    revoked: vec![],
                    excluded: vec![],
                    certifications: vec![],
                    transactions: vec![dubp_user_docs_tests_tools::mocks::tx::first_g1_tx_doc()],
                });
            assert_eq!(
                expected_block,
                parse_json_block(&block_json_value).expect("Fail to parse block_json_value !")
            );
    
            expected_block.verify_inner_hash()?;
            Ok(())
        }
    }