From d0cabad492e1328324e9686e0d9206f7cd431481 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Tue, 30 Oct 2018 19:22:32 +0100
Subject: [PATCH] documents : change crate structure & migrate regex -> pest
---
Cargo.lock | 122 +++-
blockchain/apply_valid_block.rs | 6 +-
blockchain/check_and_apply_block.rs | 2 +-
blockchain/dbex.rs | 2 +-
blockchain/lib.rs | 4 +-
blockchain/revert_block.rs | 6 +-
blockchain/ts_parsers.rs | 18 +-
dal/block.rs | 4 +-
dal/currency_params.rs | 2 +-
dal/dal_event.rs | 5 +-
dal/dal_requests.rs | 8 +-
dal/identity.rs | 2 +-
dal/lib.rs | 4 +-
dal/parsers/certifications.rs | 4 +-
dal/parsers/revoked.rs | 4 +-
dal/sources.rs | 2 +-
dal/writers/block.rs | 2 +-
dal/writers/certification.rs | 2 +-
dal/writers/dividend.rs | 2 +-
dal/writers/identity.rs | 4 +-
dal/writers/requests.rs | 4 +-
dal/writers/transaction.rs | 17 +-
documents/Cargo.toml | 5 +-
documents/blockchain/v10/mod.rs | 18 -
documents/lib.rs | 271 --------
documents/src/blockstamp.rs | 144 ++++
documents/{ => src}/currencies_codes.rs | 0
documents/src/documents_grammar.pest | 162 +++++
documents/{blockchain/mod.rs => src/lib.rs} | 272 ++++----
.../v10/documents => src/v10}/block.rs | 42 +-
.../documents => src/v10}/certification.rs | 158 +++--
.../v10/documents => src/v10}/identity.rs | 123 ++--
.../v10/documents => src/v10}/membership.rs | 156 ++---
.../v10/documents => src/v10}/mod.rs | 345 ++++++----
.../v10/documents => src/v10}/revocation.rs | 141 ++--
.../v10/documents => src/v10}/transaction.rs | 637 +++++++++---------
message/lib.rs | 2 +-
network/lib.rs | 14 +-
network/network_head.rs | 13 +-
network/network_head_v2.rs | 13 +-
network/network_head_v3.rs | 2 +-
network/network_peer.rs | 2 +-
ws2p-messages/lib.rs | 2 +-
ws2p-messages/v2/payload_container.rs | 10 +-
ws2p-messages/v2/req_responses.rs | 8 +-
ws2p-v1-legacy/lib.rs | 2 +-
ws2p-v1-legacy/parsers/blocks.rs | 6 +-
ws2p-v1-legacy/parsers/identities.rs | 5 +-
ws2p-v1-legacy/parsers/memberships.rs | 7 +-
ws2p-v1-legacy/parsers/mod.rs | 23 +-
ws2p-v1-legacy/parsers/transactions.rs | 17 +-
51 files changed, 1494 insertions(+), 1332 deletions(-)
delete mode 100644 documents/blockchain/v10/mod.rs
delete mode 100644 documents/lib.rs
create mode 100644 documents/src/blockstamp.rs
rename documents/{ => src}/currencies_codes.rs (100%)
create mode 100644 documents/src/documents_grammar.pest
rename documents/{blockchain/mod.rs => src/lib.rs} (54%)
rename documents/{blockchain/v10/documents => src/v10}/block.rs (96%)
rename documents/{blockchain/v10/documents => src/v10}/certification.rs (67%)
rename documents/{blockchain/v10/documents => src/v10}/identity.rs (67%)
rename documents/{blockchain/v10/documents => src/v10}/membership.rs (69%)
rename documents/{blockchain/v10/documents => src/v10}/mod.rs (59%)
rename documents/{blockchain/v10/documents => src/v10}/revocation.rs (63%)
rename documents/{blockchain/v10/documents => src/v10}/transaction.rs (62%)
diff --git a/Cargo.lock b/Cargo.lock
index 47891302..1bf7ce43 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -14,6 +14,11 @@ dependencies = [
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "arrayref"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "arrayvec"
version = "0.4.7"
@@ -86,6 +91,20 @@ name = "bitflags"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "block-buffer"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "byte-tools"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "byteorder"
version = "1.2.3"
@@ -170,6 +189,14 @@ name = "difference"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "digest"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "dirs"
version = "1.0.2"
@@ -287,7 +314,8 @@ dependencies = [
"duniter-crypto 0.2.0-a0.1",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -463,6 +491,11 @@ dependencies = [
"synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "fake-simd"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "foreign-types"
version = "0.3.2"
@@ -495,6 +528,14 @@ name = "gcc"
version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "generic-array"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "httparse"
version = "1.3.0"
@@ -580,6 +621,11 @@ dependencies = [
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "maplit"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "matches"
version = "0.1.6"
@@ -703,6 +749,45 @@ name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "pest"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_generator 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_meta 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "pkg-config"
version = "0.3.11"
@@ -900,6 +985,17 @@ dependencies = [
"serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "sha-1"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "sha1"
version = "0.6.0"
@@ -1067,6 +1163,16 @@ dependencies = [
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "typenum"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "ucd-util"
version = "0.1.1"
@@ -1198,6 +1304,7 @@ dependencies = [
[metadata]
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1"
"checksum backtrace 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbdd17cd962b570302f5297aea8648d5923e22e555c2ed2d8b2e34eca646bf6d"
@@ -1207,6 +1314,8 @@ dependencies = [
"checksum bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f2fb9e29e72fd6bc12071533d5dc7664cb01480c59406f656d7ac25c7bd8ff7"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
+"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
+"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
"checksum bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd32989a66957d3f0cba6588f15d4281a733f4e9ffc43fcd2385f57d3bf99ff"
"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
@@ -1217,16 +1326,19 @@ dependencies = [
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
+"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
"checksum dirs 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "37a76dd8b997af7107d0bb69d43903cf37153a18266f8b3fdb9911f28efb5444"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
+"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
+"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
"checksum httparse 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "422d5a93b40dbfbd8c8c24d1b4b5ef455973ef3afffc172487429fecd05bde42"
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
@@ -1239,6 +1351,7 @@ dependencies = [
"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
"checksum log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fddaa003a65722a7fb9e26b0ce95921fe4ba590542ced664d8ce2fa26f9f3ac"
"checksum log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae0136257df209261daa18d6c16394757c63e032e27aafd8b07788b051082bef"
+"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
@@ -1253,6 +1366,10 @@ dependencies = [
"checksum openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)" = "d8abc04833dcedef24221a91852931df2f63e3369ae003134e70aff3645775cc"
"checksum pbr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "deb73390ab68d81992bd994d145f697451bb0b54fd39738e72eef32458ad6907"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
+"checksum pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a677051ad923732bb5c70f2d45f8985a96e3eee2e2bff86697e3b11b0c3fcfde"
+"checksum pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b76f477146419bc539a63f4ef40e902166cb43b3e51cecc71d9136fd12c567e7"
+"checksum pest_generator 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebee4e9680be4fd162e6f3394ae4192a6b60b1e4d17d845e631f0c68d1a3386"
+"checksum pest_meta 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f6d5f6f0e6082578c86af197d780dc38328e3f768cec06aac9bc46d714e8221"
"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f"
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6"
@@ -1277,6 +1394,7 @@ dependencies = [
"checksum serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)" = "92ec94e2754699adddbbc4f555791bd3acc2a2f5574cba16c93a4a9cf4a04415"
"checksum serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "0a90213fa7e0f5eac3f7afe2d5ff6b088af515052cc7303bd68c7e3b91a3fb79"
"checksum serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "eb40600c756f02d7ea34943626cefa85732fdae5f95b90b31f9797b3c526d1e6"
+"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
"checksum simplelog 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9cc12b39fdf4c9a07f88bffac2d628f0118ed5ac077a4b0feece61fadf1429e5"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
@@ -1297,6 +1415,8 @@ dependencies = [
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
+"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
+"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
diff --git a/blockchain/apply_valid_block.rs b/blockchain/apply_valid_block.rs
index 69e72f30..698ff041 100644
--- a/blockchain/apply_valid_block.rs
+++ b/blockchain/apply_valid_block.rs
@@ -18,10 +18,10 @@ use duniter_dal::block::DALBlock;
use duniter_dal::sources::SourceAmount;
use duniter_dal::writers::requests::*;
use duniter_dal::{BinDB, ForkId};
-use duniter_documents::blockchain::v10::documents::transaction::{TxAmount, TxBase};
-use duniter_documents::blockchain::v10::documents::BlockDocument;
-use duniter_documents::blockchain::Document;
+use duniter_documents::v10::transaction::{TxAmount, TxBase};
+use duniter_documents::v10::BlockDocument;
use duniter_documents::BlockId;
+use duniter_documents::Document;
use durs_wot::data::{NewLinkResult, RemLinkResult};
use durs_wot::{NodeId, WebOfTrust};
use std::collections::{HashMap, HashSet};
diff --git a/blockchain/check_and_apply_block.rs b/blockchain/check_and_apply_block.rs
index 3c601f47..8b5b7e35 100644
--- a/blockchain/check_and_apply_block.rs
+++ b/blockchain/check_and_apply_block.rs
@@ -19,7 +19,7 @@ use apply_valid_block::*;
use duniter_crypto::keys::*;
use duniter_dal::block::DALBlock;
use duniter_dal::*;
-use duniter_documents::blockchain::Document;
+use duniter_documents::Document;
use duniter_documents::{BlockHash, BlockId, Blockstamp, PreviousBlockstamp};
use duniter_network::NetworkBlock;
use *;
diff --git a/blockchain/dbex.rs b/blockchain/dbex.rs
index 34ede624..5e7736d9 100644
--- a/blockchain/dbex.rs
+++ b/blockchain/dbex.rs
@@ -15,7 +15,7 @@
use duniter_crypto::keys::*;
use duniter_dal::identity::DALIdentity;
-use duniter_documents::blockchain::v10::documents::transaction::*;
+use duniter_documents::v10::transaction::*;
use duniter_module::DuniterConf;
use durs_wot::data::rusty::RustyWebOfTrust;
use durs_wot::operations::distance::{DistanceCalculator, WotDistance, WotDistanceParameters};
diff --git a/blockchain/lib.rs b/blockchain/lib.rs
index 50397e5f..02e0a4ff 100644
--- a/blockchain/lib.rs
+++ b/blockchain/lib.rs
@@ -70,9 +70,9 @@ use duniter_dal::dal_requests::{DALReqBlockchain, DALRequest, DALResBlockchain,
use duniter_dal::identity::DALIdentity;
use duniter_dal::writers::requests::BlocksDBsWriteQuery;
use duniter_dal::*;
-use duniter_documents::blockchain::v10::documents::{BlockDocument, V10Document};
-use duniter_documents::blockchain::{BlockchainProtocol, Document};
+use duniter_documents::v10::{BlockDocument, V10Document};
use duniter_documents::*;
+use duniter_documents::{BlockchainProtocol, Document};
use duniter_message::*;
use duniter_module::*;
use duniter_network::{
diff --git a/blockchain/revert_block.rs b/blockchain/revert_block.rs
index 3ea7afc0..1492efb6 100644
--- a/blockchain/revert_block.rs
+++ b/blockchain/revert_block.rs
@@ -19,9 +19,9 @@ use duniter_dal::sources::SourceAmount;
use duniter_dal::writers::requests::*;
use duniter_dal::writers::transaction::DALTxV10;
use duniter_dal::{BinDB, ForkId, TxV10Datas};
-use duniter_documents::blockchain::v10::documents::block::TxDocOrTxHash;
-use duniter_documents::blockchain::v10::documents::transaction::{TxAmount, TxBase};
-use duniter_documents::blockchain::Document;
+use duniter_documents::v10::block::TxDocOrTxHash;
+use duniter_documents::v10::transaction::{TxAmount, TxBase};
+use duniter_documents::Document;
use durs_wot::data::{NewLinkResult, RemLinkResult};
use durs_wot::{NodeId, WebOfTrust};
use std::collections::HashMap;
diff --git a/blockchain/ts_parsers.rs b/blockchain/ts_parsers.rs
index e41c1f00..26e32387 100644
--- a/blockchain/ts_parsers.rs
+++ b/blockchain/ts_parsers.rs
@@ -18,13 +18,13 @@ extern crate sqlite;
use duniter_crypto::hashs::Hash;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::block::{BlockV10Parameters, TxDocOrTxHash};
-use duniter_documents::blockchain::v10::documents::identity::IdentityDocumentBuilder;
-use duniter_documents::blockchain::v10::documents::membership::*;
-use duniter_documents::blockchain::v10::documents::transaction::*;
-use duniter_documents::blockchain::v10::documents::*;
-use duniter_documents::blockchain::DocumentBuilder;
+use duniter_documents::v10::block::{BlockV10Parameters, TxDocOrTxHash};
+use duniter_documents::v10::identity::*;
+use duniter_documents::v10::membership::*;
+use duniter_documents::v10::transaction::*;
+use duniter_documents::v10::*;
use duniter_documents::CurrencyName;
+use duniter_documents::DocumentBuilder;
use duniter_documents::{BlockHash, BlockId, Blockstamp};
use duniter_network::{NetworkBlock, NetworkBlockV10};
use std::str::FromStr;
@@ -329,7 +329,7 @@ pub fn parse_transaction(
let mut inputs = Vec::with_capacity(inputs_array.len());
for input in inputs_array {
let input_str = input.as_str()?;
- match TransactionInput::parse_from_str(input_str) {
+ match TransactionInput::from_str(input_str) {
Ok(input) => inputs.push(input),
Err(_) => {
return None;
@@ -339,7 +339,7 @@ pub fn parse_transaction(
let unlocks_array = source.get("unlocks")?.as_array()?;
let mut unlocks = Vec::with_capacity(unlocks_array.len());
for unlock in unlocks_array {
- match TransactionInputUnlocks::parse_from_str(unlock.as_str()?) {
+ match TransactionInputUnlocks::from_str(unlock.as_str()?) {
Ok(unlock) => unlocks.push(unlock),
Err(_) => {
return None;
@@ -350,7 +350,7 @@ pub fn parse_transaction(
let mut outputs = Vec::with_capacity(outputs_array.len());
for output in outputs_array {
outputs.push(
- TransactionOutput::parse_from_str(
+ TransactionOutput::from_str(
output
.as_str()
.unwrap_or_else(|| panic!("Fail to parse output : {:?}", output)),
diff --git a/dal/block.rs b/dal/block.rs
index 5a35d938..2dc072dd 100644
--- a/dal/block.rs
+++ b/dal/block.rs
@@ -15,8 +15,8 @@
use super::constants::MAX_FORKS;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::BlockDocument;
-use duniter_documents::blockchain::Document;
+use duniter_documents::v10::BlockDocument;
+use duniter_documents::Document;
use duniter_documents::{BlockHash, BlockId, Blockstamp, PreviousBlockstamp};
use durs_wot::NodeId;
use std::collections::HashMap;
diff --git a/dal/currency_params.rs b/dal/currency_params.rs
index e0ab8a0c..5b902385 100644
--- a/dal/currency_params.rs
+++ b/dal/currency_params.rs
@@ -14,7 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use constants::*;
-use duniter_documents::blockchain::v10::documents::block::BlockV10Parameters;
+use duniter_documents::v10::block::BlockV10Parameters;
use duniter_documents::CurrencyName;
use *;
diff --git a/dal/dal_event.rs b/dal/dal_event.rs
index cdc27e5e..9a487dee 100644
--- a/dal/dal_event.rs
+++ b/dal/dal_event.rs
@@ -13,9 +13,8 @@
// 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/>.
-use duniter_documents::blockchain::v10::documents::BlockDocument;
-use duniter_documents::blockchain::BlockchainProtocol;
-use duniter_documents::Blockstamp;
+use duniter_documents::v10::block::BlockDocument;
+use duniter_documents::*;
#[derive(Debug, Clone)]
/// Event to be transmitted to the other modules
diff --git a/dal/dal_requests.rs b/dal/dal_requests.rs
index 52fc8383..9a3a8604 100644
--- a/dal/dal_requests.rs
+++ b/dal/dal_requests.rs
@@ -19,9 +19,11 @@ extern crate serde;
use self::duniter_module::ModuleReqId;
use duniter_crypto::hashs::Hash;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::{
- BlockDocument, CertificationDocument, IdentityDocument, MembershipDocument, RevocationDocument,
-};
+use duniter_documents::v10::block::BlockDocument;
+use duniter_documents::v10::certification::CertificationDocument;
+use duniter_documents::v10::identity::IdentityDocument;
+use duniter_documents::v10::membership::MembershipDocument;
+use duniter_documents::v10::revocation::RevocationDocument;
use duniter_documents::Blockstamp;
use std::collections::HashMap;
diff --git a/dal/identity.rs b/dal/identity.rs
index 30d36b4e..86dad5ac 100644
--- a/dal/identity.rs
+++ b/dal/identity.rs
@@ -15,7 +15,7 @@
use currency_params::CurrencyParameters;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::IdentityDocument;
+use duniter_documents::v10::identity::IdentityDocument;
use duniter_documents::{BlockId, Blockstamp};
use durs_wot::NodeId;
use std::collections::HashMap;
diff --git a/dal/lib.rs b/dal/lib.rs
index b0181eb0..07093a9a 100644
--- a/dal/lib.rs
+++ b/dal/lib.rs
@@ -81,8 +81,8 @@ pub mod writers;
use duniter_crypto::hashs::Hash;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::block::BlockV10Parameters;
-use duniter_documents::blockchain::v10::documents::transaction::*;
+use duniter_documents::v10::block::BlockV10Parameters;
+use duniter_documents::v10::transaction::*;
use duniter_documents::CurrencyName;
use duniter_documents::{BlockHash, BlockId, Blockstamp, PreviousBlockstamp};
use durs_wot::{NodeId, WebOfTrust};
diff --git a/dal/parsers/certifications.rs b/dal/parsers/certifications.rs
index 675894f5..e5753986 100644
--- a/dal/parsers/certifications.rs
+++ b/dal/parsers/certifications.rs
@@ -17,8 +17,8 @@ extern crate serde;
extern crate serde_json;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::certification::CompactCertificationDocument;
-use duniter_documents::blockchain::v10::documents::{CertificationDocument, TextDocumentFormat};
+use duniter_documents::v10::certification::{CertificationDocument, CompactCertificationDocument};
+use duniter_documents::v10::TextDocumentFormat;
use duniter_documents::BlockId;
/// Parse array of certification json documents into vector of `CompactCertificationDocument`
diff --git a/dal/parsers/revoked.rs b/dal/parsers/revoked.rs
index 03779cdf..2b22e996 100644
--- a/dal/parsers/revoked.rs
+++ b/dal/parsers/revoked.rs
@@ -16,8 +16,8 @@
extern crate serde_json;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::revocation::CompactRevocationDocument;
-use duniter_documents::blockchain::v10::documents::{RevocationDocument, TextDocumentFormat};
+use duniter_documents::v10::revocation::{CompactRevocationDocument, RevocationDocument};
+use duniter_documents::v10::TextDocumentFormat;
/// Parse array of revocations json documents into vector of `CompactRevocationDocument`
pub fn parse_revocations_into_compact(
diff --git a/dal/sources.rs b/dal/sources.rs
index 54a40a54..8d020059 100644
--- a/dal/sources.rs
+++ b/dal/sources.rs
@@ -18,7 +18,7 @@ extern crate duniter_documents;
use duniter_crypto::hashs::Hash;
use duniter_crypto::keys::PubKey;
-use duniter_documents::blockchain::v10::documents::transaction::*;
+use duniter_documents::v10::transaction::*;
use duniter_documents::BlockId;
use std::cmp::Ordering;
use std::ops::{Add, Sub};
diff --git a/dal/writers/block.rs b/dal/writers/block.rs
index d447ad41..a716aa44 100644
--- a/dal/writers/block.rs
+++ b/dal/writers/block.rs
@@ -14,7 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use block::DALBlock;
-use duniter_documents::blockchain::Document;
+use duniter_documents::Document;
use duniter_documents::{BlockHash, BlockId, PreviousBlockstamp};
use std::collections::HashMap;
use ForkId;
diff --git a/dal/writers/certification.rs b/dal/writers/certification.rs
index bb01dfd1..bb61ffe8 100644
--- a/dal/writers/certification.rs
+++ b/dal/writers/certification.rs
@@ -18,7 +18,7 @@ extern crate serde_json;
use currency_params::CurrencyParameters;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::certification::CompactCertificationDocument;
+use duniter_documents::v10::certification::CompactCertificationDocument;
use duniter_documents::BlockId;
use durs_wot::NodeId;
use {BinDB, CertsExpirV10Datas, DALError, IdentitiesV10Datas};
diff --git a/dal/writers/dividend.rs b/dal/writers/dividend.rs
index 648240fb..4b2b97a2 100644
--- a/dal/writers/dividend.rs
+++ b/dal/writers/dividend.rs
@@ -14,7 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use duniter_crypto::keys::PubKey;
-use duniter_documents::blockchain::v10::documents::transaction::*;
+use duniter_documents::v10::transaction::*;
use duniter_documents::BlockId;
use sources::SourceAmount;
use std::collections::{HashMap, HashSet};
diff --git a/dal/writers/identity.rs b/dal/writers/identity.rs
index 93f2bef0..a491d006 100644
--- a/dal/writers/identity.rs
+++ b/dal/writers/identity.rs
@@ -15,8 +15,8 @@
use currency_params::CurrencyParameters;
use duniter_crypto::keys::PubKey;
-use duniter_documents::blockchain::v10::documents::IdentityDocument;
-use duniter_documents::blockchain::Document;
+use duniter_documents::v10::identity::IdentityDocument;
+use duniter_documents::Document;
use duniter_documents::{BlockId, Blockstamp};
use durs_wot::NodeId;
use identity::{DALIdentity, DALIdentityState};
diff --git a/dal/writers/requests.rs b/dal/writers/requests.rs
index 825a14af..5e00a01d 100644
--- a/dal/writers/requests.rs
+++ b/dal/writers/requests.rs
@@ -19,8 +19,8 @@ extern crate serde_json;
use block::DALBlock;
use currency_params::CurrencyParameters;
use duniter_crypto::keys::PubKey;
-use duniter_documents::blockchain::v10::documents::certification::CompactCertificationDocument;
-use duniter_documents::blockchain::v10::documents::identity::IdentityDocument;
+use duniter_documents::v10::certification::CompactCertificationDocument;
+use duniter_documents::v10::identity::IdentityDocument;
use duniter_documents::Blockstamp;
use durs_wot::NodeId;
use identity::DALIdentity;
diff --git a/dal/writers/transaction.rs b/dal/writers/transaction.rs
index b0733ebe..a7c23d1f 100644
--- a/dal/writers/transaction.rs
+++ b/dal/writers/transaction.rs
@@ -13,7 +13,8 @@
// 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/>.
-use duniter_documents::blockchain::v10::documents::transaction::*;
+use duniter_documents::v10::transaction::*;
+
use sources::{SourceAmount, SourceIndexV10, UTXOIndexV10, UTXOV10};
use *;
@@ -413,7 +414,8 @@ pub fn apply_and_write_tx(
#[cfg(test)]
mod tests {
use super::*;
- use duniter_documents::blockchain::{Document, DocumentBuilder, VerificationResult};
+ use duniter_documents::{Document, DocumentBuilder, VerificationResult};
+ use std::str::FromStr;
fn build_first_tx_of_g1() -> TransactionDocument {
let pubkey = PubKey::Ed25519(
@@ -432,18 +434,19 @@ mod tests {
blockstamp: &block,
locktime: &0,
issuers: &vec![pubkey],
- inputs: &vec![TransactionInput::parse_from_str(
+ inputs: &vec![TransactionInput::from_str(
"1000:0:D:2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ:1",
)
.expect("fail to parse input !")],
- unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)")
- .expect("fail to parse unlock !")],
+ unlocks: &vec![
+ TransactionInputUnlocks::from_str("0:SIG(0)").expect("fail to parse unlock !")
+ ],
outputs: &vec![
- TransactionOutput::parse_from_str(
+ TransactionOutput::from_str(
"1:0:SIG(Com8rJukCozHZyFao6AheSsfDQdPApxQRnz7QYFf64mm)",
)
.expect("fail to parse output !"),
- TransactionOutput::parse_from_str(
+ TransactionOutput::from_str(
"999:0:SIG(2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ)",
)
.expect("fail to parse output !"),
diff --git a/documents/Cargo.toml b/documents/Cargo.toml
index 0f6fd6ff..a0633f80 100644
--- a/documents/Cargo.toml
+++ b/documents/Cargo.toml
@@ -9,7 +9,7 @@ keywords = ["duniter", "blockchain", "cryptocurrency", "document"]
license = "AGPL-3.0"
[lib]
-path = "lib.rs"
+path = "src/lib.rs"
[dependencies]
base58 = "0.1.*"
@@ -18,7 +18,8 @@ byteorder = "1.2.3"
duniter-crypto = { path = "../crypto" }
lazy_static = "1.0.*"
linked-hash-map = "0.5.*"
-regex = "1.0.*"
+pest = "2.0"
+pest_derive = "2.0"
rust-crypto = "0.2.*"
serde = "1.0.*"
serde_derive = "1.0.*"
diff --git a/documents/blockchain/v10/mod.rs b/documents/blockchain/v10/mod.rs
deleted file mode 100644
index 9b3d159d..00000000
--- a/documents/blockchain/v10/mod.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (C) 2018 The Duniter Project Developers.
-//
-// 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/>.
-
-//! Provide wrappers around Duniter V10 documents and events.
-
-pub mod documents;
diff --git a/documents/lib.rs b/documents/lib.rs
deleted file mode 100644
index 04f20fac..00000000
--- a/documents/lib.rs
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright (C) 2018 The Duniter Project Developers.
-//
-// 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/>.
-
-//! Implements the Duniter Documents Protocol.
-
-#![cfg_attr(feature = "strict", deny(warnings))]
-#![deny(
- missing_docs,
- missing_debug_implementations,
- missing_copy_implementations,
- trivial_casts,
- trivial_numeric_casts,
- unsafe_code,
- unstable_features,
- unused_import_braces,
- unused_qualifications
-)]
-
-#[macro_use]
-extern crate lazy_static;
-#[macro_use]
-extern crate serde_derive;
-
-extern crate base58;
-extern crate base64;
-extern crate byteorder;
-extern crate crypto;
-extern crate duniter_crypto;
-extern crate linked_hash_map;
-extern crate regex;
-extern crate serde;
-
-use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
-use currencies_codes::*;
-use duniter_crypto::hashs::Hash;
-use std::cmp::Ordering;
-use std::fmt::{Debug, Display, Error, Formatter};
-use std::io::Cursor;
-use std::mem;
-
-pub mod blockchain;
-mod currencies_codes;
-
-/// Currency name
-#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, Hash)]
-pub struct CurrencyName(pub String);
-
-impl Default for CurrencyName {
- fn default() -> CurrencyName {
- CurrencyName(String::from("default_currency"))
- }
-}
-
-impl Display for CurrencyName {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
- write!(f, "{}", self.0)
- }
-}
-
-/// CurrencyCodeError
-#[derive(Debug)]
-pub enum CurrencyCodeError {
- /// UnknowCurrencyCode
- UnknowCurrencyCode(),
- /// IoError
- IoError(::std::io::Error),
- /// UnknowCurrencyName
- UnknowCurrencyName(),
-}
-
-impl From<::std::io::Error> for CurrencyCodeError {
- fn from(error: ::std::io::Error) -> Self {
- CurrencyCodeError::IoError(error)
- }
-}
-
-impl CurrencyName {
- /// Convert bytes to CurrencyName
- pub fn from(currency_code: [u8; 2]) -> Result<Self, CurrencyCodeError> {
- let mut currency_code_bytes = Cursor::new(currency_code.to_vec());
- let currency_code = currency_code_bytes.read_u16::<BigEndian>()?;
- Self::from_u16(currency_code)
- }
- /// Convert u16 to CurrencyName
- pub fn from_u16(currency_code: u16) -> Result<Self, CurrencyCodeError> {
- match currency_code {
- tmp if tmp == *CURRENCY_NULL => Ok(CurrencyName(String::from(""))),
- tmp if tmp == *CURRENCY_G1 => Ok(CurrencyName(String::from("g1"))),
- tmp if tmp == *CURRENCY_G1_TEST => Ok(CurrencyName(String::from("g1-test"))),
- _ => Err(CurrencyCodeError::UnknowCurrencyCode()),
- }
- }
- /// Convert CurrencyName to bytes
- pub fn to_bytes(&self) -> Result<[u8; 2], CurrencyCodeError> {
- let currency_code = match self.0.as_str() {
- "g1" => *CURRENCY_G1,
- "g1-test" => *CURRENCY_G1_TEST,
- _ => return Err(CurrencyCodeError::UnknowCurrencyName()),
- };
- let mut buffer = [0u8; mem::size_of::<u16>()];
- buffer
- .as_mut()
- .write_u16::<BigEndian>(currency_code)
- .expect("Unable to write");
- Ok(buffer)
- }
-}
-
-/// A block Id.
-#[derive(Copy, Clone, Debug, Deserialize, Ord, PartialEq, PartialOrd, Eq, Hash, Serialize)]
-pub struct BlockId(pub u32);
-
-impl Display for BlockId {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
- write!(f, "{}", self.0)
- }
-}
-
-/// Wrapper of a block hash.
-#[derive(Copy, Clone, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Hash, Serialize)]
-pub struct BlockHash(pub Hash);
-
-impl Display for BlockHash {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
- write!(f, "{}", self.0.to_hex())
- }
-}
-
-impl Debug for BlockHash {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
- write!(f, "BlockHash({})", self)
- }
-}
-
-/// Type of errors for [`BlockUId`] parsing.
-///
-/// [`BlockUId`]: struct.BlockUId.html
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum BlockUIdParseError {
- /// Given string have invalid format
- InvalidFormat(),
- /// [`BlockId`](struct.BlockHash.html) part is not a valid number.
- InvalidBlockId(),
- /// [`BlockHash`](struct.BlockHash.html) part is not a valid hex number.
- InvalidBlockHash(),
-}
-
-/// A blockstamp (Unique ID).
-///
-/// It's composed of the [`BlockId`] and
-/// the [`BlockHash`] of the block.
-///
-/// Thanks to blockchain immutability and frequent block production, it can
-/// be used to date information.
-///
-/// [`BlockId`]: struct.BlockId.html
-/// [`BlockHash`]: struct.BlockHash.html
-
-#[derive(Copy, Clone, Deserialize, PartialEq, Eq, Hash, Serialize)]
-pub struct Blockstamp {
- /// Block Id.
- pub id: BlockId,
- /// Block hash.
- pub hash: BlockHash,
-}
-
-/// Previous blockstamp (BlockId-1, previous_hash)
-pub type PreviousBlockstamp = Blockstamp;
-
-impl Blockstamp {
- /// Blockstamp size (in bytes).
- pub const SIZE_IN_BYTES: usize = 36;
-}
-
-impl Display for Blockstamp {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
- write!(f, "{}-{}", self.id, self.hash)
- }
-}
-
-impl Debug for Blockstamp {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
- write!(f, "BlockUId({})", self)
- }
-}
-
-impl Default for Blockstamp {
- fn default() -> Blockstamp {
- Blockstamp {
- id: BlockId(0),
- hash: BlockHash(Hash::default()),
- }
- }
-}
-
-impl PartialOrd for Blockstamp {
- fn partial_cmp(&self, other: &Blockstamp) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for Blockstamp {
- fn cmp(&self, other: &Blockstamp) -> Ordering {
- if self.id == other.id {
- self.hash.cmp(&other.hash)
- } else {
- self.id.cmp(&other.id)
- }
- }
-}
-
-#[derive(Debug)]
-/// Error when converting a byte vector to Blockstamp
-pub enum ReadBytesBlockstampError {
- /// Bytes vector is too short
- TooShort(),
- /// Bytes vector is too long
- TooLong(),
- /// IoError
- IoError(::std::io::Error),
-}
-
-impl From<::std::io::Error> for ReadBytesBlockstampError {
- fn from(e: ::std::io::Error) -> Self {
- ReadBytesBlockstampError::IoError(e)
- }
-}
-
-impl Blockstamp {
- /// Create a `BlockUId` from a text.
- pub fn from_string(src: &str) -> Result<Blockstamp, BlockUIdParseError> {
- let mut split = src.split('-');
-
- if split.clone().count() != 2 {
- Err(BlockUIdParseError::InvalidFormat())
- } else {
- let id = split.next().unwrap().parse::<u32>();
- let hash = Hash::from_hex(split.next().unwrap());
-
- if id.is_err() {
- Err(BlockUIdParseError::InvalidBlockId())
- } else if hash.is_err() {
- Err(BlockUIdParseError::InvalidBlockHash())
- } else {
- Ok(Blockstamp {
- id: BlockId(id.unwrap()),
- hash: BlockHash(
- hash.expect("Try to get hash of an uncompleted or reduce block !"),
- ),
- })
- }
- }
- }
-
- /// Convert a `BlockUId` to its text format.
- pub fn to_string(&self) -> String {
- format!("{}", self)
- }
-}
diff --git a/documents/src/blockstamp.rs b/documents/src/blockstamp.rs
new file mode 100644
index 00000000..a81d70af
--- /dev/null
+++ b/documents/src/blockstamp.rs
@@ -0,0 +1,144 @@
+// Copyright (C) 2018 The Duniter Project Developers.
+//
+// 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/>.
+
+//! Wrapper for blockstamp
+
+use *;
+
+/// Type of errors for [`BlockUId`] parsing.
+///
+/// [`BlockUId`]: struct.BlockUId.html
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum BlockstampParseError {
+ /// Given string have invalid format
+ InvalidFormat(),
+ /// [`BlockId`](struct.BlockHash.html) part is not a valid number.
+ InvalidBlockId(),
+ /// [`BlockHash`](struct.BlockHash.html) part is not a valid hex number.
+ InvalidBlockHash(),
+}
+
+/// A blockstamp (Unique ID).
+///
+/// It's composed of the [`BlockId`] and
+/// the [`BlockHash`] of the block.
+///
+/// Thanks to blockchain immutability and frequent block production, it can
+/// be used to date information.
+///
+/// [`BlockId`]: struct.BlockId.html
+/// [`BlockHash`]: struct.BlockHash.html
+
+#[derive(Copy, Clone, Deserialize, PartialEq, Eq, Hash, Serialize)]
+pub struct Blockstamp {
+ /// Block Id.
+ pub id: BlockId,
+ /// Block hash.
+ pub hash: BlockHash,
+}
+
+/// Previous blockstamp (BlockId-1, previous_hash)
+pub type PreviousBlockstamp = Blockstamp;
+
+impl Blockstamp {
+ /// Blockstamp size (in bytes).
+ pub const SIZE_IN_BYTES: usize = 36;
+}
+
+impl Display for Blockstamp {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ write!(f, "{}-{}", self.id, self.hash)
+ }
+}
+
+impl Debug for Blockstamp {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ write!(f, "BlockUId({})", self)
+ }
+}
+
+impl Default for Blockstamp {
+ fn default() -> Blockstamp {
+ Blockstamp {
+ id: BlockId(0),
+ hash: BlockHash(Hash::default()),
+ }
+ }
+}
+
+impl PartialOrd for Blockstamp {
+ fn partial_cmp(&self, other: &Blockstamp) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Blockstamp {
+ fn cmp(&self, other: &Blockstamp) -> Ordering {
+ if self.id == other.id {
+ self.hash.cmp(&other.hash)
+ } else {
+ self.id.cmp(&other.id)
+ }
+ }
+}
+
+#[derive(Debug)]
+/// Error when converting a byte vector to Blockstamp
+pub enum ReadBytesBlockstampError {
+ /// Bytes vector is too short
+ TooShort(),
+ /// Bytes vector is too long
+ TooLong(),
+ /// IoError
+ IoError(::std::io::Error),
+}
+
+impl From<::std::io::Error> for ReadBytesBlockstampError {
+ fn from(e: ::std::io::Error) -> Self {
+ ReadBytesBlockstampError::IoError(e)
+ }
+}
+
+impl Blockstamp {
+ /// Create a `BlockUId` from a text.
+ pub fn from_string(src: &str) -> Result<Blockstamp, BlockstampParseError> {
+ let mut split = src.split('-');
+
+ if split.clone().count() != 2 {
+ Err(BlockstampParseError::InvalidFormat())
+ } else {
+ let id = split.next().unwrap().parse::<u32>();
+ let hash = Hash::from_hex(split.next().unwrap());
+
+ if id.is_err() {
+ Err(BlockstampParseError::InvalidBlockId())
+ } else if hash.is_err() {
+ Err(BlockstampParseError::InvalidBlockHash())
+ } else {
+ Ok(Blockstamp {
+ id: BlockId(id.unwrap()),
+ hash: BlockHash(
+ hash.expect("Try to get hash of an uncompleted or reduce block !"),
+ ),
+ })
+ }
+ }
+ }
+
+ /// Convert a `BlockUId` to its text format.
+ pub fn to_string(&self) -> String {
+ format!("{}", self)
+ }
+}
diff --git a/documents/currencies_codes.rs b/documents/src/currencies_codes.rs
similarity index 100%
rename from documents/currencies_codes.rs
rename to documents/src/currencies_codes.rs
diff --git a/documents/src/documents_grammar.pest b/documents/src/documents_grammar.pest
new file mode 100644
index 00000000..cc509f5f
--- /dev/null
+++ b/documents/src/documents_grammar.pest
@@ -0,0 +1,162 @@
+nl = _{ "\n" }
+hexa = { ASCII_DIGIT | 'A'..'F' }
+base58 = { !("O" | "I" | "l") ~ ASCII_ALPHANUMERIC }
+base64 = { ASCII_ALPHANUMERIC | "+" | "/" }
+
+integer = @{ "0" | ('1'..'9' ~ ASCII_DIGIT*) }
+hash = @{ hexa{64} }
+
+currency = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "-" | "_")* }
+pubkey = @{ base58{43,44} }
+uid = @{ ASCII_ALPHA+ }
+block_id = @{ integer }
+blockstamp = ${ block_id ~ "-" ~ hash }
+ed25519_sig = @{ base64{86,88} ~ "="{0,2} }
+
+v10 = _{ "Version: 10" }
+
+idty_v10 = ${
+ v10 ~ nl ~
+ "Type: Identity" ~ nl ~
+ "Currency: " ~ currency ~ nl ~
+ "Issuer: " ~ pubkey ~ nl ~
+ "UniqueID: " ~ uid ~ nl ~
+ "Timestamp: " ~ blockstamp ~ nl ~
+ ed25519_sig? ~ nl*
+}
+
+idty = ${
+ SOI ~
+ (&(v10 ~ nl) ~ idty_v10)
+ ~ EOI
+}
+
+membership_in = @{ "IN" }
+membership_out = @{ "OUT" }
+
+membership_v10 = ${
+ v10 ~ nl ~
+ "Type: Membership" ~ nl ~
+ "Currency: " ~ currency ~ nl ~
+ "Issuer: " ~ pubkey ~ nl ~
+ "Block: " ~ blockstamp ~ nl ~
+ "Membership: " ~ (membership_in | membership_out) ~ nl ~
+ "UserID: " ~ uid ~ nl ~
+ "CertTS: " ~ blockstamp ~ nl ~
+ ed25519_sig? ~ nl*
+}
+
+membership = ${
+ SOI ~
+ (&("Version: 10" ~ nl) ~ membership_v10)
+ ~ EOI
+}
+
+cert_v10 = ${
+ v10 ~ nl ~
+ "Type: Certification" ~ nl ~
+ "Currency: " ~ currency ~ nl ~
+ "Issuer: " ~ pubkey ~ nl ~
+ "IdtyIssuer: " ~ pubkey ~ nl ~
+ "IdtyUniqueID: " ~ uid ~ nl ~
+ "IdtyTimestamp: " ~ blockstamp ~ nl ~
+ "IdtySignature: " ~ ed25519_sig ~ nl ~
+ "CertTimestamp: " ~ blockstamp ~ nl ~
+ ed25519_sig? ~ nl*
+}
+
+cert = ${
+ SOI ~
+ (&("Version: 10" ~ nl) ~ cert_v10)
+ ~ EOI
+}
+
+revoc_v10 = ${
+ v10 ~ nl ~
+ "Type: Revocation" ~ nl ~
+ "Currency: " ~ currency ~ nl ~
+ "Issuer: " ~ pubkey ~ nl ~
+ "IdtyUniqueID: " ~ uid ~ nl ~
+ "IdtyTimestamp: " ~ blockstamp ~ nl ~
+ "IdtySignature: " ~ ed25519_sig ~ nl ~
+ ed25519_sig? ~ nl*
+}
+
+revoc = ${
+ SOI ~
+ (&("Version: 10" ~ nl) ~ revoc_v10)
+ ~ EOI
+}
+
+tx_locktime = @{ integer }
+tx_amount = @{ integer }
+tx_amount_base = @{ integer }
+du_block_id = @{ integer }
+tx_index = @{ integer }
+input_index = @{ integer }
+issuer_index = @{ integer }
+xhx_secret = @ { ASCII_ALPHANUMERIC+ }
+csv_duration = @{ integer }
+cltv_timestamp = @{ integer }
+
+tx_input = ${ tx_input_du | tx_input_tx }
+tx_input_du = ${ tx_amount ~ ":" ~ tx_amount_base ~ ":D:" ~ pubkey ~ ":" ~ du_block_id }
+tx_input_tx = ${ tx_amount ~ ":" ~ tx_amount_base ~ ":T:" ~ hash ~ ":" ~ tx_index }
+
+tx_unlock = ${ input_index ~ ":" ~ unlock_cond ~ (" " ~ unlock_cond)* }
+unlock_cond = _{ unlock_sig | unlock_xhx }
+unlock_sig = ${ "SIG(" ~ issuer_index ~ ")" }
+unlock_xhx = ${ "XHX(" ~ xhx_secret ~ ")" }
+
+tx_output = ${ tx_amount ~ ":" ~ tx_amount_base ~ ":" ~ output_conds_group }
+output_conds_group = _{ output_and_group | output_or_group | output_single_cond }
+output_and_group = ${ "(" ~ output_conds_group ~ (" && " ~ output_conds_group)+ ~ ")" }
+output_or_group = ${ "(" ~ output_conds_group ~ (" || " ~ output_conds_group)+ ~ ")" }
+output_single_cond = _{ output_cond_sig | output_cond_xhx | output_cond_csv | output_cond_cltv }
+output_cond_sig = ${ "SIG(" ~ pubkey ~ ")"? }
+output_cond_xhx = ${ "XHX(" ~ hash ~ ")"? }
+output_cond_csv = ${ "CSV(" ~ csv_duration ~ ")"? }
+output_cond_cltv = ${ "CLTV(" ~ cltv_timestamp ~ ")"? }
+
+tx_comment_char = {
+ ASCII_ALPHANUMERIC | "\\" | ":" | "/" | ";" | "*" | "[" | "]" | "(" | ")" | "?" | "!" | "^"
+ | "+" | "=" | "@" | "&" | "~" | "#" | "{" | "}" | "|" | "<" | ">" | "%" | "." | " " | "-"
+}
+tx_comment = @{ tx_comment_char{0,255} }
+
+tx_v10 = ${
+ "Version: 10" ~ nl ~
+ "Type: Transaction" ~ nl ~
+ "Currency: " ~ currency ~ nl ~
+ "Blockstamp: " ~ blockstamp ~ nl ~
+ "Locktime: " ~ tx_locktime ~ nl ~
+ "Issuers:" ~ nl ~ (pubkey ~ nl)+ ~
+ "Inputs:" ~ nl ~ (tx_input ~ nl)+ ~
+ "Unlocks:" ~ nl ~ (tx_unlock ~ nl)+ ~
+ "Outputs:" ~ nl ~ (tx_output ~ nl)+ ~
+ "Comment: " ~ tx_comment ~ nl ~
+ (ed25519_sig ~ nl)* ~ // intermediate signatures (zero if the transaction has only one signature)
+ ed25519_sig? ~ nl* // last signature
+}
+
+tx = ${
+ SOI ~
+ (&("Version: 10" ~ nl) ~ tx_v10)
+ ~ EOI
+}
+
+document_v10 = ${
+ SOI ~
+ (&"Type: Identity" ~ idty_v10) |
+ (&"Type: Membership" ~ membership_v10) |
+ (&"Type: Certification" ~ cert_v10) |
+ (&"Type: Revocation" ~ revoc_v10) |
+ (&"Type: Transaction" ~ tx_v10)
+ ~ EOI
+}
+
+document = ${
+ SOI ~
+ (&("Version: 10" ~ nl) ~ document_v10)
+ ~ EOI
+}
diff --git a/documents/blockchain/mod.rs b/documents/src/lib.rs
similarity index 54%
rename from documents/blockchain/mod.rs
rename to documents/src/lib.rs
index 64edf826..9ee020c3 100644
--- a/documents/blockchain/mod.rs
+++ b/documents/src/lib.rs
@@ -13,25 +13,152 @@
// 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/>.
-//! Provide wrappers around Duniter documents and events.
-
-use std::fmt::Debug;
+//! Implements the Duniter Documents Protocol.
+
+#![cfg_attr(feature = "strict", deny(warnings))]
+#![deny(
+ missing_debug_implementations,
+ missing_copy_implementations,
+ trivial_casts,
+ trivial_numeric_casts,
+ unsafe_code,
+ unstable_features,
+ unused_import_braces
+)]
+
+extern crate base58;
+extern crate base64;
+extern crate byteorder;
+extern crate crypto;
+extern crate duniter_crypto;
+extern crate linked_hash_map;
+extern crate pest;
+#[macro_use]
+extern crate pest_derive;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
+
+pub mod blockstamp;
+mod currencies_codes;
+pub mod v10;
-use duniter_crypto::keys::{PrivateKey, PublicKey};
+use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
+use currencies_codes::*;
+use duniter_crypto::hashs::Hash;
+use duniter_crypto::keys::*;
+use std::cmp::Ordering;
+use std::fmt::{Debug, Display, Error, Formatter};
+use std::io::Cursor;
+use std::mem;
-use super::Blockstamp;
+pub use blockstamp::{Blockstamp, PreviousBlockstamp};
-pub mod v10;
+#[derive(Parser)]
+#[grammar = "documents_grammar.pest"]
+/// Parser for Documents
+struct DocumentsParser;
/// List of blockchain protocol versions.
#[derive(Debug, Clone)]
pub enum BlockchainProtocol {
/// Version 10.
- V10(Box<v10::documents::V10Document>),
+ V10(Box<v10::V10Document>),
/// Version 11. (not done yet, but defined for tests)
V11(),
}
+/// Currency name
+#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, Hash)]
+pub struct CurrencyName(pub String);
+
+impl Default for CurrencyName {
+ fn default() -> CurrencyName {
+ CurrencyName(String::from("default_currency"))
+ }
+}
+
+impl Display for CurrencyName {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ write!(f, "{}", self.0)
+ }
+}
+
+/// CurrencyCodeError
+#[derive(Debug)]
+pub enum CurrencyCodeError {
+ /// UnknowCurrencyCode
+ UnknowCurrencyCode(),
+ /// IoError
+ IoError(::std::io::Error),
+ /// UnknowCurrencyName
+ UnknowCurrencyName(),
+}
+
+impl From<::std::io::Error> for CurrencyCodeError {
+ fn from(error: ::std::io::Error) -> Self {
+ CurrencyCodeError::IoError(error)
+ }
+}
+
+impl CurrencyName {
+ /// Convert bytes to CurrencyName
+ pub fn from(currency_code: [u8; 2]) -> Result<Self, CurrencyCodeError> {
+ let mut currency_code_bytes = Cursor::new(currency_code.to_vec());
+ let currency_code = currency_code_bytes.read_u16::<BigEndian>()?;
+ Self::from_u16(currency_code)
+ }
+ /// Convert u16 to CurrencyName
+ pub fn from_u16(currency_code: u16) -> Result<Self, CurrencyCodeError> {
+ match currency_code {
+ tmp if tmp == *CURRENCY_NULL => Ok(CurrencyName(String::from(""))),
+ tmp if tmp == *CURRENCY_G1 => Ok(CurrencyName(String::from("g1"))),
+ tmp if tmp == *CURRENCY_G1_TEST => Ok(CurrencyName(String::from("g1-test"))),
+ _ => Err(CurrencyCodeError::UnknowCurrencyCode()),
+ }
+ }
+ /// Convert CurrencyName to bytes
+ pub fn to_bytes(&self) -> Result<[u8; 2], CurrencyCodeError> {
+ let currency_code = match self.0.as_str() {
+ "g1" => *CURRENCY_G1,
+ "g1-test" => *CURRENCY_G1_TEST,
+ _ => return Err(CurrencyCodeError::UnknowCurrencyName()),
+ };
+ let mut buffer = [0u8; mem::size_of::<u16>()];
+ buffer
+ .as_mut()
+ .write_u16::<BigEndian>(currency_code)
+ .expect("Unable to write");
+ Ok(buffer)
+ }
+}
+
+/// A block Id.
+#[derive(Copy, Clone, Debug, Deserialize, Ord, PartialEq, PartialOrd, Eq, Hash, Serialize)]
+pub struct BlockId(pub u32);
+
+impl Display for BlockId {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ write!(f, "{}", self.0)
+ }
+}
+
+/// Wrapper of a block hash.
+#[derive(Copy, Clone, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Hash, Serialize)]
+pub struct BlockHash(pub Hash);
+
+impl Display for BlockHash {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ write!(f, "{}", self.0.to_hex())
+ }
+}
+
+impl Debug for BlockHash {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ write!(f, "BlockHash({})", self)
+ }
+}
+
/// trait providing commun methods for any documents of any protocol version.
///
/// # Design choice
@@ -139,134 +266,3 @@ pub trait DocumentParser<S, D, E> {
/// Parse a source and return a document or an error.
fn parse(source: S) -> Result<D, E>;
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use duniter_crypto::keys::*;
-
- // simple text document for signature testing
- #[derive(Debug, Clone)]
- struct PlainTextDocument {
- pub text: &'static str,
- pub issuers: Vec<PubKey>,
- pub signatures: Vec<Sig>,
- }
-
- impl Document for PlainTextDocument {
- type PublicKey = PubKey;
- type CurrencyType = str;
-
- fn version(&self) -> u16 {
- unimplemented!()
- }
-
- fn currency(&self) -> &str {
- unimplemented!()
- }
-
- fn blockstamp(&self) -> Blockstamp {
- unimplemented!()
- }
-
- fn issuers(&self) -> &Vec<PubKey> {
- &self.issuers
- }
-
- fn signatures(&self) -> &Vec<Sig> {
- &self.signatures
- }
-
- fn as_bytes(&self) -> &[u8] {
- self.text.as_bytes()
- }
- }
-
- #[test]
- fn verify_signatures() {
- let text = "Version: 10
-Type: Identity
-Currency: duniter_unit_test_currency
-Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-UniqueID: tic
-Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-";
-
- // good pair
- let issuer1 = PubKey::Ed25519(
- ed25519::PublicKey::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV")
- .unwrap(),
- );
-
- let sig1 = Sig::Ed25519(
- ed25519::Signature::from_base64(
- "1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMM\
- mQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==",
- )
- .unwrap(),
- );
-
- // incorrect pair
- let issuer2 = PubKey::Ed25519(
- ed25519::PublicKey::from_base58("DNann1Lh55eZMEDXeYt32bzHbA3NJR46DeQYCS2qQdLV")
- .unwrap(),
- );
-
- let sig2 = Sig::Ed25519(
- ed25519::Signature::from_base64(
- "1eubHHbuNfilHHH0G2bI30iZzebQ2cQ1PC7uPAw08FGMM\
- mQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==",
- )
- .unwrap(),
- );
-
- {
- let doc = PlainTextDocument {
- text,
- issuers: vec![issuer1],
- signatures: vec![sig1],
- };
-
- assert_eq!(doc.verify_signatures(), VerificationResult::Valid());
- }
-
- {
- let doc = PlainTextDocument {
- text,
- issuers: vec![issuer1],
- signatures: vec![sig2],
- };
-
- assert_eq!(
- doc.verify_signatures(),
- VerificationResult::Invalid(vec![0])
- );
- }
-
- {
- let doc = PlainTextDocument {
- text,
- issuers: vec![issuer1, issuer2],
- signatures: vec![sig1],
- };
-
- assert_eq!(
- doc.verify_signatures(),
- VerificationResult::IncompletePairs(2, 1)
- );
- }
-
- {
- let doc = PlainTextDocument {
- text,
- issuers: vec![issuer1],
- signatures: vec![sig1, sig2],
- };
-
- assert_eq!(
- doc.verify_signatures(),
- VerificationResult::IncompletePairs(1, 2)
- );
- }
- }
-}
diff --git a/documents/blockchain/v10/documents/block.rs b/documents/src/v10/block.rs
similarity index 96%
rename from documents/blockchain/v10/documents/block.rs
rename to documents/src/v10/block.rs
index 72db06e6..b03e00f2 100644
--- a/documents/blockchain/v10/documents/block.rs
+++ b/documents/src/v10/block.rs
@@ -19,17 +19,16 @@ use crypto::digest::Digest;
use crypto::sha2::Sha256;
use duniter_crypto::hashs::Hash;
use duniter_crypto::keys::*;
-
-use blockchain::v10::documents::certification::CertificationDocument;
-use blockchain::v10::documents::identity::IdentityDocument;
-use blockchain::v10::documents::membership::MembershipDocument;
-use blockchain::v10::documents::revocation::RevocationDocument;
-use blockchain::v10::documents::transaction::TransactionDocument;
-use blockchain::v10::documents::*;
-use blockchain::{BlockchainProtocol, Document, IntoSpecializedDocument};
use std::ops::Deref;
-use CurrencyName;
-use {BlockHash, BlockId, Blockstamp};
+
+use blockstamp::Blockstamp;
+use v10::certification::CertificationDocument;
+use v10::identity::IdentityDocument;
+use v10::membership::MembershipDocument;
+use v10::revocation::RevocationDocument;
+use v10::transaction::TransactionDocument;
+use v10::*;
+use *;
#[derive(Debug, Clone)]
/// Store error in block parameters parsing
@@ -510,10 +509,11 @@ impl IntoSpecializedDocument<BlockchainProtocol> for BlockDocument {
#[cfg(test)]
mod tests {
+ use super::certification::CertificationDocumentParser;
+ use super::transaction::TransactionDocumentParser;
use super::*;
- use blockchain::v10::documents::V10DocumentParser;
- use blockchain::{Document, DocumentParser, VerificationResult};
use std::ops::Deref;
+ use {Document, VerificationResult};
#[test]
fn generate_and_verify_empty_block() {
@@ -575,7 +575,7 @@ mod tests {
#[test]
fn generate_and_verify_block() {
- let cert1_ = V10DocumentParser::parse("Version: 10
+ let cert1 = CertificationDocumentParser::parse("Version: 10
Type: Certification
Currency: g1
Issuer: 6TAzLWuNcSqgNDNpAutrKpPXcGJwy1ZEMeVvZSZNs2e3
@@ -584,13 +584,13 @@ IdtyUniqueID: PascaleM
IdtyTimestamp: 97401-0000003821911909F98519CC773D2D3E5CFE3D5DBB39F4F4FF33B96B4D41800E
IdtySignature: QncUVXxZ2NfARjdJOn6luILvDuG1NuK9qSoaU4CST2Ij8z7oeVtEgryHl+EXOjSe6XniALsCT0gU8wtadcA/Cw==
CertTimestamp: 106669-000003682E6FE38C44433DCE92E8B2A26C69B6D7867A2BAED231E788DDEF4251
-UmseG2XKNwKcY8RFi6gUCT91udGnnNmSh7se10J1jeRVlwf+O2Tyb2Cccot9Dt7BO4+Kx2P6vFJB3oVGGHMxBA==").unwrap();
- let cert1 = match cert1_ {
+UmseG2XKNwKcY8RFi6gUCT91udGnnNmSh7se10J1jeRVlwf+O2Tyb2Cccot9Dt7BO4+Kx2P6vFJB3oVGGHMxBA==", "g1").expect("Fail to parse cert1");
+ let cert1 = match cert1 {
V10Document::Certification(doc) => (*doc.deref()).clone(),
_ => panic!("Wrong document type"),
};
- let tx1_ = V10DocumentParser::parse("Version: 10
+ let tx1 = TransactionDocumentParser::parse("Version: 10
Type: Transaction
Currency: g1
Blockstamp: 107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
@@ -604,13 +604,13 @@ Unlocks:
Outputs:
1002:0:SIG(CitdnuQgZ45tNFCagay7Wh12gwwHM8VLej1sWmfHWnQX)
Comment: DU symbolique pour demander le codage de nouvelles fonctionnalites cf. https://forum.monnaie-libre.fr/t/creer-de-nouvelles-fonctionnalites-dans-cesium-les-autres-applications/2025 Merci
-T0LlCcbIn7xDFws48H8LboN6NxxwNXXTovG4PROLf7tkUAueHFWjfwZFKQXeZEHxfaL1eYs3QspGtLWUHPRVCQ==").unwrap();
- let tx1 = match tx1_ {
+T0LlCcbIn7xDFws48H8LboN6NxxwNXXTovG4PROLf7tkUAueHFWjfwZFKQXeZEHxfaL1eYs3QspGtLWUHPRVCQ==", "g1").expect("Fail to parse tx1");
+ let tx1 = match tx1 {
V10Document::Transaction(doc) => (*doc.deref()).clone(),
_ => panic!("Wrong document type"),
};
- let tx2_ = V10DocumentParser::parse("Version: 10
+ let tx2 = TransactionDocumentParser::parse("Version: 10
Type: Transaction
Currency: g1
Blockstamp: 107982-000001242F6DA51C06A915A96C58BAA37AB3D1EB51F6E1C630C707845ACF764B
@@ -624,8 +624,8 @@ Unlocks:
Outputs:
1002:0:SIG(78ZwwgpgdH5uLZLbThUQH7LKwPgjMunYfLiCfUCySkM8)
Comment: DU symbolique pour demander le codage de nouvelles fonctionnalites cf. https://forum.monnaie-libre.fr/t/creer-de-nouvelles-fonctionnalites-dans-cesium-les-autres-applications/2025 Merci
-a9PHPuSfw7jW8FRQHXFsGi/bnLjbtDnTYvEVgUC9u0WlR7GVofa+Xb+l5iy6NwuEXiwvueAkf08wPVY8xrNcCg==").unwrap();
- let tx2 = match tx2_ {
+a9PHPuSfw7jW8FRQHXFsGi/bnLjbtDnTYvEVgUC9u0WlR7GVofa+Xb+l5iy6NwuEXiwvueAkf08wPVY8xrNcCg==", "g1").expect("Fail to parse tx2");
+ let tx2 = match tx2 {
V10Document::Transaction(doc) => (*doc.deref()).clone(),
_ => panic!("Wrong document type"),
};
diff --git a/documents/blockchain/v10/documents/certification.rs b/documents/src/v10/certification.rs
similarity index 67%
rename from documents/blockchain/v10/documents/certification.rs
rename to documents/src/v10/certification.rs
index e03213f0..00ec4df8 100644
--- a/documents/blockchain/v10/documents/certification.rs
+++ b/documents/src/v10/certification.rs
@@ -16,18 +16,11 @@
//! Wrappers around Certification documents.
use duniter_crypto::keys::*;
-use regex::Regex;
+use pest::Parser;
-use blockchain::v10::documents::*;
-use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
-use BlockId;
-use Blockstamp;
-
-lazy_static! {
- static ref CERTIFICATION_REGEX: Regex = Regex::new(
- "^Issuer: (?P<issuer>[1-9A-Za-z]{43,44})\nIdtyIssuer: (?P<target>[1-9A-Za-z]{43,44})\nIdtyUniqueID: (?P<idty_uid>[[:alnum:]_-]+)\nIdtyTimestamp: (?P<idty_blockstamp>[0-9]+-[0-9A-F]{64})\nIdtySignature: (?P<idty_sig>(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)\nCertTimestamp: (?P<blockstamp>[0-9]+-[0-9A-F]{64})\n$"
- ).unwrap();
-}
+use blockstamp::Blockstamp;
+use v10::*;
+use *;
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
/// Wrap an Compact Revocation document (in block content)
@@ -124,7 +117,7 @@ impl Document for CertificationDocument {
}
fn as_bytes(&self) -> &[u8] {
- self.as_text().as_bytes()
+ self.as_text_without_signature().as_bytes()
}
}
@@ -228,47 +221,74 @@ CertTimestamp: {blockstamp}
#[derive(Debug, Clone, Copy)]
pub struct CertificationDocumentParser;
-impl StandardTextDocumentParser for CertificationDocumentParser {
- fn parse_standard(
- doc: &str,
- body: &str,
- currency: &str,
- signatures: Vec<Sig>,
- ) -> Result<V10Document, V10DocumentParsingError> {
- if let Some(caps) = CERTIFICATION_REGEX.captures(body) {
- let issuer = &caps["issuer"];
- let target = &caps["target"];
- let identity_username = &caps["idty_uid"];
- let identity_blockstamp = &caps["idty_blockstamp"];
- let identity_sig = &caps["idty_sig"];
- let blockstamp = &caps["blockstamp"];
-
- // Regex match so should not fail.
- // TODO : Test it anyway
- let issuer = PubKey::Ed25519(ed25519::PublicKey::from_base58(issuer).unwrap());
- let target = PubKey::Ed25519(ed25519::PublicKey::from_base58(target).unwrap());
- let identity_username = String::from(identity_username);
- let identity_blockstamp = Blockstamp::from_string(identity_blockstamp).unwrap();
- let identity_sig = Sig::Ed25519(ed25519::Signature::from_base64(identity_sig).unwrap());
- let blockstamp = Blockstamp::from_string(blockstamp).unwrap();
-
- Ok(V10Document::Certification(Box::new(
- CertificationDocument {
- text: doc.to_owned(),
- issuers: vec![issuer],
- currency: currency.to_owned(),
- target,
- identity_username,
- identity_blockstamp,
- identity_sig,
- blockstamp,
- signatures,
- },
- )))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(
- "Certification".to_string(),
- ))
+impl TextDocumentParser for CertificationDocumentParser {
+ fn parse(doc: &str, currency: &str) -> Result<V10Document, V10DocumentParsingError> {
+ match DocumentsParser::parse(Rule::cert, doc) {
+ Ok(mut doc_ast) => {
+ let cert_ast = doc_ast.next().unwrap(); // get and unwrap the `cert` rule; never fails
+ let cert_vx_ast = cert_ast.into_inner().next().unwrap(); // get and unwrap the `cert_vX` rule; never fails
+
+ match cert_vx_ast.as_rule() {
+ Rule::cert_v10 => {
+ let mut pubkeys = Vec::with_capacity(2);
+ let mut uid = "";
+ let mut sigs = Vec::with_capacity(2);
+ let mut blockstamps = Vec::with_capacity(2);
+ for field in cert_vx_ast.into_inner() {
+ match field.as_rule() {
+ Rule::currency => {
+ if currency != field.as_str() {
+ return Err(V10DocumentParsingError::InvalidCurrency());
+ }
+ }
+ Rule::pubkey => pubkeys.push(PubKey::Ed25519(
+ ed25519::PublicKey::from_base58(field.as_str()).unwrap(), // Grammar ensures that we have a base58 string.
+ )),
+ Rule::uid => {
+ uid = field.as_str();
+ }
+ Rule::blockstamp => {
+ if blockstamps.len() > 1 {
+ return Err(V10DocumentParsingError::InvalidInnerFormat(
+ "Cert document must contain exactly two blockstamps !",
+ ));
+ }
+ let mut inner_rules = field.into_inner(); // { integer ~ "-" ~ hash }
+
+ let block_id: &str = inner_rules.next().unwrap().as_str();
+ let block_hash: &str = inner_rules.next().unwrap().as_str();
+ blockstamps.push(Blockstamp {
+ id: BlockId(block_id.parse().unwrap()), // Grammar ensures that we have a digits string.
+ hash: BlockHash(Hash::from_hex(block_hash).unwrap()), // Grammar ensures that we have an hexadecimal string.
+ });
+ }
+ Rule::ed25519_sig => {
+ sigs.push(Sig::Ed25519(
+ ed25519::Signature::from_base64(field.as_str()).unwrap(), // Grammar ensures that we have a base64 string.
+ ));
+ }
+ Rule::EOI => (),
+ _ => panic!("unexpected rule"), // Grammar ensures that we never reach this line
+ }
+ }
+ Ok(V10Document::Certification(Box::new(
+ CertificationDocument {
+ text: doc.to_owned(),
+ issuers: vec![pubkeys[0]],
+ currency: currency.to_owned(),
+ target: pubkeys[1],
+ identity_username: uid.to_owned(),
+ identity_blockstamp: blockstamps[0],
+ identity_sig: sigs[0],
+ blockstamp: blockstamps[1],
+ signatures: vec![sigs[1]],
+ },
+ )))
+ }
+ _ => Err(V10DocumentParsingError::UnexpectedVersion()),
+ }
+ }
+ Err(pest_error) => panic!("{}", pest_error), //Err(V10DocumentParsingError::PestError()),
}
}
}
@@ -276,8 +296,8 @@ impl StandardTextDocumentParser for CertificationDocumentParser {
#[cfg(test)]
mod tests {
use super::*;
- use blockchain::VerificationResult;
use duniter_crypto::keys::{PrivateKey, PublicKey, Signature};
+ use VerificationResult;
#[test]
fn generate_real_document() {
@@ -334,19 +354,6 @@ mod tests {
);
}
- #[test]
- fn certification_standard_regex() {
- assert!(CERTIFICATION_REGEX.is_match(
- "Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-IdtyIssuer: 7jzkd8GiFnpys4X7mP78w2Y3y3kwdK6fVSLEaojd3aH9
-IdtyUniqueID: fbarbut
-IdtyTimestamp: 98221-000000575AC04F5164F7A307CDB766139EA47DD249E4A2444F292BC8AAB408B3
-IdtySignature: DjeipIeb/RF0tpVCnVnuw6mH1iLJHIsDfPGLR90Twy3PeoaDz6Yzhc/UjLWqHCi5Y6wYajV0dNg4jQRUneVBCQ==
-CertTimestamp: 99956-00000472758331FDA8388E30E50CA04736CBFD3B7C21F34E74707107794B56DD
-"
- ));
- }
-
#[test]
fn certification_document() {
let doc = "Version: 10
@@ -358,24 +365,11 @@ IdtyUniqueID: mmpio
IdtyTimestamp: 7543-000044410C5370DE8DBA911A358F318096B7A269CFC2BB93272E397CC513EA0A
IdtySignature: SmSweUD4lEMwiZfY8ux9maBjrQQDkC85oMNsin6oSQCPdXG8sFCZ4FisUaWqKsfOlZVb/HNa+TKzD2t0Yte+DA==
CertTimestamp: 167884-0001DFCA28002A8C96575E53B8CEF8317453A7B0BA255542CCF0EC8AB5E99038
-";
-
- let body = "Issuer: 5B8iMAzq1dNmFe3ZxFTBQkqhq4fsztg1gZvxHXCk1XYH
-IdtyIssuer: mMPioknj2MQCX9KyKykdw8qMRxYR2w1u3UpdiEJHgXg
-IdtyUniqueID: mmpio
-IdtyTimestamp: 7543-000044410C5370DE8DBA911A358F318096B7A269CFC2BB93272E397CC513EA0A
-IdtySignature: SmSweUD4lEMwiZfY8ux9maBjrQQDkC85oMNsin6oSQCPdXG8sFCZ4FisUaWqKsfOlZVb/HNa+TKzD2t0Yte+DA==
-CertTimestamp: 167884-0001DFCA28002A8C96575E53B8CEF8317453A7B0BA255542CCF0EC8AB5E99038
-";
+wqZxPEGxLrHGv8VdEIfUGvUcf+tDdNTMXjLzVRCQ4UhlhDRahOMjfcbP7byNYr5OfIl83S1MBxF7VJgu8YasCA==";
let currency = "g1-test";
- let signatures = vec![Sig::Ed25519(ed25519::Signature::from_base64(
-"wqZxPEGxLrHGv8VdEIfUGvUcf+tDdNTMXjLzVRCQ4UhlhDRahOMjfcbP7byNYr5OfIl83S1MBxF7VJgu8YasCA=="
- ).unwrap())];
-
- let doc =
- CertificationDocumentParser::parse_standard(doc, body, currency, signatures).unwrap();
+ let doc = CertificationDocumentParser::parse(doc, currency).unwrap();
if let V10Document::Certification(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid());
diff --git a/documents/blockchain/v10/documents/identity.rs b/documents/src/v10/identity.rs
similarity index 67%
rename from documents/blockchain/v10/documents/identity.rs
rename to documents/src/v10/identity.rs
index 4eacf71e..fb228f5f 100644
--- a/documents/blockchain/v10/documents/identity.rs
+++ b/documents/src/v10/identity.rs
@@ -15,16 +15,11 @@
//! Wrappers around Identity documents.
-use blockchain::v10::documents::*;
-use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
-use regex::Regex;
-use Blockstamp;
+use pest::Parser;
-lazy_static! {
- static ref IDENTITY_REGEX: Regex = Regex::new(
- "^Issuer: (?P<issuer>[1-9A-Za-z][^OIl]{43,44})\nUniqueID: (?P<uid>[[:alnum:]_-]+)\nTimestamp: (?P<blockstamp>[0-9]+-[0-9A-F]{64})\n$"
- ).unwrap();
-}
+use v10::*;
+use Blockstamp;
+use *;
/// Wrap an Identity document.
///
@@ -86,7 +81,7 @@ impl Document for IdentityDocument {
}
fn as_bytes(&self) -> &[u8] {
- self.as_text().as_bytes()
+ self.as_text_without_signature().as_bytes()
}
}
@@ -204,35 +199,60 @@ Timestamp: {blockstamp}
#[derive(Debug, Clone, Copy)]
pub struct IdentityDocumentParser;
-impl StandardTextDocumentParser for IdentityDocumentParser {
- fn parse_standard(
- doc: &str,
- body: &str,
- currency: &str,
- signatures: Vec<Sig>,
- ) -> Result<V10Document, V10DocumentParsingError> {
- if let Some(caps) = IDENTITY_REGEX.captures(body) {
- let issuer = &caps["issuer"];
- let uid = &caps["uid"];
- let blockstamp = &caps["blockstamp"];
-
- // Regex match so should not fail.
- // TODO : Test it anyway
- let issuer = PubKey::Ed25519(ed25519::PublicKey::from_base58(issuer).unwrap());
- let blockstamp = Blockstamp::from_string(blockstamp).unwrap();
-
- Ok(V10Document::Identity(IdentityDocument {
- text: Some(doc.to_owned()),
- currency: currency.to_owned(),
- username: uid.to_owned(),
- blockstamp,
- issuers: vec![issuer],
- signatures,
- }))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(
- "Identity".to_string(),
- ))
+impl TextDocumentParser for IdentityDocumentParser {
+ fn parse(doc: &str, currency: &str) -> Result<V10Document, V10DocumentParsingError> {
+ match DocumentsParser::parse(Rule::idty, doc) {
+ Ok(mut doc_ast) => {
+ let idty_ast = doc_ast.next().unwrap(); // get and unwrap the `idty` rule; never fails
+ let idty_vx_ast = idty_ast.into_inner().next().unwrap(); // get and unwrap the `idty_vX` rule; never fails
+
+ match idty_vx_ast.as_rule() {
+ Rule::idty_v10 => {
+ let mut pubkey_str = "";
+ let mut uid = "";
+ let mut blockstamp = Blockstamp::default();
+ let mut sig_str = "";
+ for field in idty_vx_ast.into_inner() {
+ match field.as_rule() {
+ Rule::currency => {
+ if currency != field.as_str() {
+ return Err(V10DocumentParsingError::InvalidCurrency());
+ }
+ }
+ Rule::pubkey => pubkey_str = field.as_str(),
+ Rule::uid => uid = field.as_str(),
+ Rule::blockstamp => {
+ let mut inner_rules = field.into_inner(); // { integer ~ "-" ~ hash }
+
+ let block_id: &str = inner_rules.next().unwrap().as_str();
+ let block_hash: &str = inner_rules.next().unwrap().as_str();
+ blockstamp = Blockstamp {
+ id: BlockId(block_id.parse().unwrap()), // Grammar ensures that we have a digits string.
+ hash: BlockHash(Hash::from_hex(block_hash).unwrap()), // Grammar ensures that we have an hexadecimal string.
+ };
+ }
+ Rule::ed25519_sig => sig_str = field.as_str(),
+ Rule::EOI => (),
+ _ => panic!("unexpected rule"), // Grammar ensures that we never reach this line
+ }
+ }
+ Ok(V10Document::Identity(IdentityDocument {
+ text: Some(doc.to_owned()),
+ currency: currency.to_owned(),
+ username: uid.to_owned(),
+ blockstamp,
+ issuers: vec![PubKey::Ed25519(
+ ed25519::PublicKey::from_base58(pubkey_str).unwrap(),
+ )], // Grammar ensures that we have a base58 string.
+ signatures: vec![Sig::Ed25519(
+ ed25519::Signature::from_base64(sig_str).unwrap(),
+ )], // Grammar ensures that we have a base64 string.
+ }))
+ }
+ _ => Err(V10DocumentParsingError::UnexpectedVersion()),
+ }
+ }
+ Err(pest_error) => panic!("{}", pest_error), //Err(V10DocumentParsingError::PestError()),
}
}
}
@@ -240,8 +260,8 @@ impl StandardTextDocumentParser for IdentityDocumentParser {
#[cfg(test)]
mod tests {
use super::*;
- use blockchain::{Document, VerificationResult};
use duniter_crypto::keys::{PrivateKey, PublicKey, Signature};
+ use {Document, VerificationResult};
#[test]
fn generate_real_document() {
@@ -288,16 +308,6 @@ mod tests {
);
}
- #[test]
- fn identity_standard_regex() {
- assert!(IDENTITY_REGEX.is_match(
- "Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-UniqueID: tic
-Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-"
- ));
- }
-
#[test]
fn parse_identity_document() {
let doc = "Version: 10
@@ -306,20 +316,11 @@ Currency: duniter_unit_test_currency
Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
UniqueID: tic
Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-";
-
- let body = "Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-UniqueID: tic
-Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-";
+1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==";
let currency = "duniter_unit_test_currency";
- let signatures = vec![Sig::Ed25519(ed25519::Signature::from_base64(
-"1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg=="
- ).unwrap())];
-
- let doc = IdentityDocumentParser::parse_standard(doc, body, currency, signatures).unwrap();
+ let doc = IdentityDocumentParser::parse(doc, currency).expect("Fail to parse idty doc !");
if let V10Document::Identity(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid())
diff --git a/documents/blockchain/v10/documents/membership.rs b/documents/src/v10/membership.rs
similarity index 69%
rename from documents/blockchain/v10/documents/membership.rs
rename to documents/src/v10/membership.rs
index 3e3fb554..55eb6e46 100644
--- a/documents/blockchain/v10/documents/membership.rs
+++ b/documents/src/v10/membership.rs
@@ -16,22 +16,11 @@
//! Wrappers around Membership documents.
use duniter_crypto::keys::*;
-use regex::Regex;
-
-use blockchain::v10::documents::*;
-use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
-use Blockstamp;
-
-lazy_static! {
- static ref MEMBERSHIP_REGEX: Regex = Regex::new(
- "^Issuer: (?P<issuer>[1-9A-Za-z][^OIl]{43,44})\n\
- Block: (?P<blockstamp>[0-9]+-[0-9A-F]{64})\n\
- Membership: (?P<membership>(IN|OUT))\n\
- UserID: (?P<ity_user>[[:alnum:]_-]+)\n\
- CertTS: (?P<ity_block>[0-9]+-[0-9A-F]{64})\n$"
- )
- .unwrap();
-}
+use pest::Parser;
+
+use blockstamp::Blockstamp;
+use v10::*;
+use *;
/// Type of a Membership.
#[derive(Debug, Deserialize, Clone, Copy, Hash, Serialize, PartialEq, Eq)]
@@ -136,7 +125,7 @@ impl Document for MembershipDocument {
}
fn as_bytes(&self) -> &[u8] {
- self.as_text().as_bytes()
+ self.as_text_without_signature().as_bytes()
}
}
@@ -259,47 +248,68 @@ CertTS: {ity_blockstamp}
#[derive(Debug, Clone, Copy)]
pub struct MembershipDocumentParser;
-impl StandardTextDocumentParser for MembershipDocumentParser {
- fn parse_standard(
- doc: &str,
- body: &str,
- currency: &str,
- signatures: Vec<Sig>,
- ) -> Result<V10Document, V10DocumentParsingError> {
- if let Some(caps) = MEMBERSHIP_REGEX.captures(body) {
- let issuer = &caps["issuer"];
-
- let blockstamp = &caps["blockstamp"];
- let membership = &caps["membership"];
- let username = &caps["ity_user"];
- let ity_block = &caps["ity_block"];
-
- // Regex match so should not fail.
- // TODO : Test it anyway
- let issuer = PubKey::Ed25519(ed25519::PublicKey::from_base58(issuer).unwrap());
- let blockstamp = Blockstamp::from_string(blockstamp).unwrap();
- let membership = match membership {
- "IN" => MembershipType::In(),
- "OUT" => MembershipType::Out(),
- _ => panic!("Invalid membership type {}", membership),
- };
-
- let ity_block = Blockstamp::from_string(ity_block).unwrap();
-
- Ok(V10Document::Membership(MembershipDocument {
- text: Some(doc.to_owned()),
- issuers: vec![issuer],
- currency: currency.to_owned(),
- blockstamp,
- membership,
- identity_username: username.to_owned(),
- identity_blockstamp: ity_block,
- signatures,
- }))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(
- "Membership".to_string(),
- ))
+impl TextDocumentParser for MembershipDocumentParser {
+ fn parse(doc: &str, currency: &str) -> Result<V10Document, V10DocumentParsingError> {
+ match DocumentsParser::parse(Rule::membership, doc) {
+ Ok(mut doc_ast) => {
+ let membership_ast = doc_ast.next().unwrap(); // get and unwrap the `membership` rule; never fails
+ let membership_vx_ast = membership_ast.into_inner().next().unwrap(); // get and unwrap the `membership_vX` rule; never fails
+
+ match membership_vx_ast.as_rule() {
+ Rule::membership_v10 => {
+ let mut pubkey_str = "";
+ let mut uid = "";
+ let mut blockstamps = Vec::with_capacity(2);
+ let mut membership = MembershipType::In();
+ let mut sig_str = "";
+ for field in membership_vx_ast.into_inner() {
+ match field.as_rule() {
+ Rule::currency => {
+ if currency != field.as_str() {
+ return Err(V10DocumentParsingError::InvalidCurrency());
+ }
+ }
+ Rule::pubkey => pubkey_str = field.as_str(),
+ Rule::uid => uid = field.as_str(),
+ Rule::membership_in => membership = MembershipType::In(),
+ Rule::membership_out => membership = MembershipType::Out(),
+ Rule::blockstamp => {
+ if blockstamps.len() > 1 {
+ return Err(V10DocumentParsingError::InvalidInnerFormat("Membership document must have exactly two blockstamps !"));
+ }
+ let mut inner_rules = field.into_inner(); // { integer ~ "-" ~ hash }
+
+ let block_id: &str = inner_rules.next().unwrap().as_str();
+ let block_hash: &str = inner_rules.next().unwrap().as_str();
+ blockstamps.push(Blockstamp {
+ id: BlockId(block_id.parse().unwrap()), // Grammar ensures that we have a digits string.
+ hash: BlockHash(Hash::from_hex(block_hash).unwrap()), // Grammar ensures that we have an hexadecimal string.
+ });
+ }
+ Rule::ed25519_sig => sig_str = field.as_str(),
+ Rule::EOI => (),
+ _ => panic!("unexpected rule"), // Grammar ensures that we never reach this line
+ }
+ }
+ Ok(V10Document::Membership(MembershipDocument {
+ text: Some(doc.to_owned()),
+ issuers: vec![PubKey::Ed25519(
+ ed25519::PublicKey::from_base58(pubkey_str).unwrap(),
+ )], // Grammar ensures that we have a base58 string.
+ currency: currency.to_owned(),
+ blockstamp: blockstamps[0],
+ membership,
+ identity_username: uid.to_owned(),
+ identity_blockstamp: blockstamps[1],
+ signatures: vec![Sig::Ed25519(
+ ed25519::Signature::from_base64(sig_str).unwrap(),
+ )], // Grammar ensures that we have a base64 string.
+ }))
+ }
+ _ => Err(V10DocumentParsingError::UnexpectedVersion()),
+ }
+ }
+ Err(pest_error) => panic!("{}", pest_error), //Err(V10DocumentParsingError::PestError()),
}
}
}
@@ -307,8 +317,8 @@ impl StandardTextDocumentParser for MembershipDocumentParser {
#[cfg(test)]
mod tests {
use super::*;
- use blockchain::VerificationResult;
use duniter_crypto::keys::{PrivateKey, PublicKey, Signature};
+ use VerificationResult;
#[test]
fn generate_real_document() {
@@ -357,18 +367,6 @@ mod tests {
);
}
- #[test]
- fn membership_standard_regex() {
- assert!(MEMBERSHIP_REGEX.is_match(
- "Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-Block: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-Membership: IN
-UserID: tic
-CertTS: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-"
- ));
- }
-
#[test]
fn membership_identity_document() {
let doc = "Version: 10
@@ -379,23 +377,11 @@ Block: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
Membership: IN
UserID: tic
CertTS: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-";
-
- let body = "Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-Block: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-Membership: IN
-UserID: tic
-CertTS: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-";
+s2hUbokkibTAWGEwErw6hyXSWlWFQ2UWs2PWx8d/kkElAyuuWaQq4Tsonuweh1xn4AC1TVWt4yMR3WrDdkhnAw==";
let currency = "duniter_unit_test_currency";
- let signatures = vec![Sig::Ed25519(ed25519::Signature::from_base64(
-"s2hUbokkibTAWGEwErw6hyXSWlWFQ2UWs2PWx8d/kkElAyuuWaQq4Tsonuweh1xn4AC1TVWt4yMR3WrDdkhnAw=="
- ).unwrap())];
-
- let doc =
- MembershipDocumentParser::parse_standard(doc, body, currency, signatures).unwrap();
+ let doc = MembershipDocumentParser::parse(doc, currency).unwrap();
if let V10Document::Membership(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid());
diff --git a/documents/blockchain/v10/documents/mod.rs b/documents/src/v10/mod.rs
similarity index 59%
rename from documents/blockchain/v10/documents/mod.rs
rename to documents/src/v10/mod.rs
index 3e3d2137..0cefad22 100644
--- a/documents/blockchain/v10/documents/mod.rs
+++ b/documents/src/v10/mod.rs
@@ -15,12 +15,6 @@
//! Provide wrappers around Duniter blockchain documents for protocol version 10.
-use blockchain::v10::documents::identity::IdentityDocumentParser;
-use blockchain::{Document, DocumentBuilder, DocumentParser};
-use crypto::digest::Digest;
-use duniter_crypto::keys::*;
-use regex::Regex;
-
pub mod block;
pub mod certification;
pub mod identity;
@@ -28,31 +22,16 @@ pub mod membership;
pub mod revocation;
pub mod transaction;
-pub use blockchain::v10::documents::block::BlockDocument;
-pub use blockchain::v10::documents::certification::{
- CertificationDocument, CertificationDocumentParser,
-};
-pub use blockchain::v10::documents::identity::{IdentityDocument, IdentityDocumentBuilder};
-pub use blockchain::v10::documents::membership::{MembershipDocument, MembershipDocumentParser};
-pub use blockchain::v10::documents::revocation::{RevocationDocument, RevocationDocumentParser};
-pub use blockchain::v10::documents::transaction::{
- TransactionDocument, TransactionDocumentBuilder, TransactionDocumentParser,
-};
-
-use std::marker::Sized;
-
-// Use of lazy_static so the regex is only compiled at first use.
-lazy_static! {
- static ref DOCUMENT_REGEX: Regex = Regex::new(
- "^(?P<doc>Version: (?P<version>[0-9]+)\n\
- Type: (?P<type>[[:alpha:]]+)\n\
- Currency: (?P<currency>[[:alnum:] _-]+)\n\
- (?P<body>(?:.*\n)+?))\
- (?P<sigs>([[:alnum:]+/=]+\n)*([[:alnum:]+/=]+))$"
- )
- .unwrap();
- static ref SIGNATURES_REGEX: Regex = Regex::new("[[:alnum:]+/=]+\n?").unwrap();
-}
+use crypto::digest::Digest;
+use duniter_crypto::keys::PrivateKey;
+
+pub use v10::block::BlockDocument;
+use v10::certification::*;
+use v10::identity::*;
+use v10::membership::*;
+use v10::revocation::*;
+use v10::transaction::*;
+use *;
#[derive(Clone, Debug, Deserialize, Serialize)]
/// Contains a document in full or compact format
@@ -124,22 +103,34 @@ pub trait TextDocument: Document<PublicKey = PubKey, CurrencyType = str> {
/// Return document as text.
fn as_text(&self) -> &str;
+ /// Return document as text without signature.
+ fn as_text_without_signature(&self) -> &str {
+ let text = self.as_text();
+ let mut lines: Vec<&str> = self.as_text().split('\n').collect();
+ let sigs = self.signatures();
+ let mut sigs_str_len = sigs.len() - 1;
+ for _ in sigs {
+ sigs_str_len += lines.pop().unwrap_or("").len();
+ }
+ &text[0..(text.len() - sigs_str_len)]
+ }
+
/// Return sha256 hash of text document
fn hash<H: Digest>(&self, digest: &mut H) -> String {
digest.input_str(self.as_text());
digest.result_str()
}
- /// Return document as text with leading signatures.
+ /*/// Return document as text with leading signatures.
fn as_text_with_signatures(&self) -> String {
let mut text = self.as_text().to_string();
-
+
for sig in self.signatures() {
text = format!("{}{}\n", text, sig.to_base64());
}
-
+
text
- }
+ }*/
/// Generate compact document.
/// the compact format is the one used in the blocks.
@@ -191,9 +182,15 @@ pub enum V10DocumentParsingError {
/// The given source don't have a valid document format.
InvalidWrapperFormat(),
/// The given source don't have a valid specific document format (document type).
- InvalidInnerFormat(String),
+ InvalidInnerFormat(&'static str),
/// Type fields contains an unknown document type.
UnknownDocumentType(String),
+ /// Error with pest parser
+ PestError(),
+ /// Invalid currency
+ InvalidCurrency(),
+ /// UnexpectedVersion
+ UnexpectedVersion(),
}
/// V10 Documents in separated parts
@@ -209,134 +206,186 @@ pub struct V10DocumentParts {
pub signatures: Vec<Sig>,
}
-trait StandardTextDocumentParser {
- fn parse_standard(
- doc: &str,
- body: &str,
- currency: &str,
- signatures: Vec<Sig>,
- ) -> Result<V10Document, V10DocumentParsingError>;
+trait TextDocumentParser {
+ fn parse(doc: &str, currency: &str) -> Result<V10Document, V10DocumentParsingError>;
}
-/// A V10 document parser.
+/*/// A V10 document parser.
#[derive(Debug, Clone, Copy)]
pub struct V10DocumentParser;
impl<'a> DocumentParser<&'a str, V10Document, V10DocumentParsingError> for V10DocumentParser {
fn parse(source: &'a str) -> Result<V10Document, V10DocumentParsingError> {
- if let Some(caps) = DOCUMENT_REGEX.captures(source) {
- let doctype = &caps["type"];
- let doc = &caps["doc"];
- let currency = &caps["currency"];
- let body = &caps["body"];
- let sigs = SIGNATURES_REGEX
- .captures_iter(&caps["sigs"])
- .map(|capture| Sig::Ed25519(ed25519::Signature::from_base64(&capture[0]).unwrap()))
- .collect::<Vec<_>>();
-
- // TODO : Improve error handling of Signature::from_base64 failure
-
- match doctype {
- "Identity" => IdentityDocumentParser::parse_standard(doc, body, currency, sigs),
- "Membership" => MembershipDocumentParser::parse_standard(doc, body, currency, sigs),
- "Certification" => {
- CertificationDocumentParser::parse_standard(doc, body, currency, sigs)
- }
- "Revocation" => RevocationDocumentParser::parse_standard(doc, body, currency, sigs),
- "Transaction" => {
- TransactionDocumentParser::parse_standard(doc, body, currency, sigs)
+ /*match DocumentsParser::parse(Rule::document_v10, source) {
+ Ok(mut source_ast) => {
+ let doc_v10_ast = source_ast.next().unwrap(); // get and unwrap the `document_v10` rule; never fails
+ let doc_type_v10_ast = doc_v10_ast.into_inner().next().unwrap(); // get and unwrap the `{DOC_TYPE}_v10` rule; never fails
+
+ match doc_type_v10_ast.as_rule() {
+ Rule::idty_v10 => IdentityDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
+ Rule::membership_v10 => MembershipDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
+ Rule::cert_v10 => CertificationDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
+ Rule::revoc_v10 => RevocationDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
+ Rule::tx_v10 => TransactionDocumentParser::parse_standard(doc_type_v10_ast.as_str(), "", currency, vec![]),
}
- _ => Err(V10DocumentParsingError::UnknownDocumentType(
- doctype.to_string(),
- )),
}
- } else {
- Err(V10DocumentParsingError::InvalidWrapperFormat())
- }
- }
+ Err(_) => Err(V10DocumentParsingError::InvalidWrapperFormat()),
+ }*/
+if let Some(caps) = DOCUMENT_REGEX.captures(source) {
+let doctype = &caps["type"];
+let currency = &caps["currency"];
+
+// TODO : Improve error handling of Signature::from_base64 failure
+
+match doctype {
+"Identity" => IdentityDocumentParser::parse_standard(source, currency),
+"Membership" => MembershipDocumentParser::parse_standard(source, currency),
+"Certification" => CertificationDocumentParser::parse_standard(source, currency),
+"Revocation" => RevocationDocumentParser::parse_standard(source, currency),
+"Transaction" => TransactionDocumentParser::parse_standard(source, currency),
+_ => Err(V10DocumentParsingError::UnknownDocumentType(
+doctype.to_string(),
+)),
}
+} else {
+Err(V10DocumentParsingError::InvalidWrapperFormat())
+}
+}
+}*/
#[cfg(test)]
mod tests {
+ use super::certification::CertificationDocumentParser;
+ use super::identity::IdentityDocumentParser;
+ use super::membership::MembershipDocumentParser;
+ use super::revocation::RevocationDocumentParser;
+ use super::transaction::TransactionDocumentParser;
use super::*;
- use blockchain::{Document, VerificationResult};
+ use duniter_crypto::keys::*;
+
+ // simple text document for signature testing
+ #[derive(Debug, Clone)]
+ struct PlainTextDocument {
+ pub text: &'static str,
+ pub issuers: Vec<PubKey>,
+ pub signatures: Vec<Sig>,
+ }
- #[test]
- fn document_regex() {
- assert!(DOCUMENT_REGEX.is_match(
- "Version: 10
-Type: Transaction
-Currency: beta_brousouf
-Blockstamp: 204-00003E2B8A35370BA5A7064598F628A62D4E9EC1936BE8651CE9A85F2E06981B
-Locktime: 0
-Issuers:
-HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
-CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
-9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB
-Inputs:
-40:2:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
-70:2:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
-20:2:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
-70:2:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
-20:2:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
-15:2:D:9WYHTavL1pmhunFCzUwiiq4pXwvgGG5ysjZnjz9H8yB:46
-Unlocks:
-0:SIG(0)
-1:XHX(7665798292)
-2:SIG(0)
-3:SIG(0) SIG(2)
-4:SIG(0) SIG(1) SIG(2)
-5:SIG(2)
-Outputs:
-120:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
-146:2:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)
-49:2:(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i)\
- || XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85))
-Comment: -----@@@----- (why not this comment?)
-42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
-2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX
-2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk"
- ));
-
- assert!(DOCUMENT_REGEX.is_match(
- "Version: 10
-Type: Certification
-Currency: beta_brousouf
-Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-IdtyIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd
-IdtyUniqueID: lolcat
-IdtyTimestamp: 32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD
-IdtySignature: J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUb\
-GpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci
-CertTimestamp: 36-1076F10A7397715D2BEE82579861999EA1F274AC
-SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneNYSMV3rk"
- ));
+ impl Document for PlainTextDocument {
+ type PublicKey = PubKey;
+ type CurrencyType = str;
+
+ fn version(&self) -> u16 {
+ unimplemented!()
+ }
+
+ fn currency(&self) -> &str {
+ unimplemented!()
+ }
+
+ fn blockstamp(&self) -> Blockstamp {
+ unimplemented!()
+ }
+
+ fn issuers(&self) -> &Vec<PubKey> {
+ &self.issuers
+ }
+
+ fn signatures(&self) -> &Vec<Sig> {
+ &self.signatures
+ }
+
+ fn as_bytes(&self) -> &[u8] {
+ self.text.as_bytes()
+ }
}
#[test]
- fn signatures_regex() {
- assert_eq!(
- SIGNATURES_REGEX
- .captures_iter(
- "
-42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
-2D96KZwNUvVtcapQPq2mm7J9isFcDCfykwJpVEZwBc7tCgL4qPyu17BT5ePozAE9HS6Yvj51f62Mp4n9d9dkzJoX
-2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk"
- )
- .count(),
- 3
+ fn verify_signatures() {
+ let text = "Version: 10
+Type: Identity
+Currency: duniter_unit_test_currency
+Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
+UniqueID: tic
+Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
+";
+
+ // good pair
+ let issuer1 = PubKey::Ed25519(
+ ed25519::PublicKey::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV")
+ .unwrap(),
+ );
+
+ let sig1 = Sig::Ed25519(
+ ed25519::Signature::from_base64(
+ "1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMM\
+ mQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==",
+ )
+ .unwrap(),
);
- assert_eq!(
- SIGNATURES_REGEX
- .captures_iter(
- "
-42yQm4hGTJYWkPg39hQAUgP6S6EQ4vTfXdJuxKEHL1ih6YHiDL2hcwrFgBHjXLRgxRhj2VNVqqc6b4JayKqTE14r
-2XiBDpuUdu6zCPWGzHXXy8c4ATSscfFQG9DjmqMZUxDZVt1Dp4m2N5oHYVUfoPdrU9SLk4qxi65RNrfCVnvQtQJk"
- )
- .count(),
- 2
+ // incorrect pair
+ let issuer2 = PubKey::Ed25519(
+ ed25519::PublicKey::from_base58("DNann1Lh55eZMEDXeYt32bzHbA3NJR46DeQYCS2qQdLV")
+ .unwrap(),
);
+
+ let sig2 = Sig::Ed25519(
+ ed25519::Signature::from_base64(
+ "1eubHHbuNfilHHH0G2bI30iZzebQ2cQ1PC7uPAw08FGMM\
+ mQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==",
+ )
+ .unwrap(),
+ );
+
+ {
+ let doc = PlainTextDocument {
+ text,
+ issuers: vec![issuer1],
+ signatures: vec![sig1],
+ };
+
+ assert_eq!(doc.verify_signatures(), VerificationResult::Valid());
+ }
+
+ {
+ let doc = PlainTextDocument {
+ text,
+ issuers: vec![issuer1],
+ signatures: vec![sig2],
+ };
+
+ assert_eq!(
+ doc.verify_signatures(),
+ VerificationResult::Invalid(vec![0])
+ );
+ }
+
+ {
+ let doc = PlainTextDocument {
+ text,
+ issuers: vec![issuer1, issuer2],
+ signatures: vec![sig1],
+ };
+
+ assert_eq!(
+ doc.verify_signatures(),
+ VerificationResult::IncompletePairs(2, 1)
+ );
+ }
+
+ {
+ let doc = PlainTextDocument {
+ text,
+ issuers: vec![issuer1],
+ signatures: vec![sig1, sig2],
+ };
+
+ assert_eq!(
+ doc.verify_signatures(),
+ VerificationResult::IncompletePairs(1, 2)
+ );
+ }
}
#[test]
@@ -349,7 +398,7 @@ UniqueID: elois
Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
Ydnclvw76/JHcKSmU9kl9Ie0ne5/X8NYOqPqbGnufIK3eEPRYYdEYaQh+zffuFhbtIRjv6m/DkVLH5cLy/IyAg==";
- let doc = V10DocumentParser::parse(text).unwrap();
+ let doc = IdentityDocumentParser::parse(text, "g1").unwrap();
if let V10Document::Identity(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid())
@@ -370,7 +419,7 @@ UserID: elois
CertTS: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==";
- let doc = V10DocumentParser::parse(text).unwrap();
+ let doc = MembershipDocumentParser::parse(text, "g1").unwrap();
if let V10Document::Membership(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid())
@@ -392,7 +441,7 @@ IdtySignature: DjeipIeb/RF0tpVCnVnuw6mH1iLJHIsDfPGLR90Twy3PeoaDz6Yzhc/UjLWqHCi5Y
CertTimestamp: 99956-00000472758331FDA8388E30E50CA04736CBFD3B7C21F34E74707107794B56DD
Hkps1QU4HxIcNXKT8YmprYTVByBhPP1U2tIM7Z8wENzLKIWAvQClkAvBE7pW9dnVa18sJIJhVZUcRrPAZfmjBA==";
- let doc = V10DocumentParser::parse(text).unwrap();
+ let doc = CertificationDocumentParser::parse(text, "g1").unwrap();
if let V10Document::Certification(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid())
@@ -412,7 +461,7 @@ IdtyTimestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B85
IdtySignature: 1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==
XXOgI++6qpY9O31ml/FcfbXCE6aixIrgkT5jL7kBle3YOMr+8wrp7Rt+z9hDVjrNfYX2gpeJsuMNfG4T/fzVDQ==";
- let doc = V10DocumentParser::parse(text).unwrap();
+ let doc = RevocationDocumentParser::parse(text, "g1").unwrap();
if let V10Document::Revocation(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid())
@@ -441,7 +490,7 @@ Outputs:
Comment: c est pour 2 mois d adhesion ressourcerie
lnpuFsIymgz7qhKF/GsZ3n3W8ZauAAfWmT4W0iJQBLKJK2GFkesLWeMj/+GBfjD6kdkjreg9M6VfkwIZH+hCCQ==";
- let doc = V10DocumentParser::parse(text).unwrap();
+ let doc = TransactionDocumentParser::parse(text, "g1").unwrap();
if let V10Document::Transaction(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid())
diff --git a/documents/blockchain/v10/documents/revocation.rs b/documents/src/v10/revocation.rs
similarity index 63%
rename from documents/blockchain/v10/documents/revocation.rs
rename to documents/src/v10/revocation.rs
index 2b059615..d4ca1983 100644
--- a/documents/blockchain/v10/documents/revocation.rs
+++ b/documents/src/v10/revocation.rs
@@ -16,20 +16,11 @@
//! Wrappers around Revocation documents.
use duniter_crypto::keys::*;
-use regex::Regex;
-
-use blockchain::v10::documents::*;
-use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
-use Blockstamp;
-
-lazy_static! {
- static ref REVOCATION_REGEX: Regex = Regex::new(
- "^Issuer: (?P<issuer>[1-9A-Za-z][^OIl]{43,44})\n\
- IdtyUniqueID: (?P<idty_uid>[[:alnum:]_-]+)\n\
- IdtyTimestamp: (?P<idty_blockstamp>[0-9]+-[0-9A-F]{64})\n\
- IdtySignature: (?P<idty_sig>(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)\n$"
- ).unwrap();
-}
+use pest::Parser;
+
+use blockstamp::Blockstamp;
+use v10::*;
+use *;
#[derive(Debug, Copy, Clone, Deserialize, Serialize, PartialEq, Eq)]
/// Wrap an Compact Revocation document (in block content)
@@ -106,7 +97,7 @@ impl Document for RevocationDocument {
}
fn as_bytes(&self) -> &[u8] {
- self.as_text().as_bytes()
+ self.as_text_without_signature().as_bytes()
}
}
@@ -198,26 +189,92 @@ IdtySignature: {idty_sig}
#[derive(Debug, Clone, Copy)]
pub struct RevocationDocumentParser;
-impl StandardTextDocumentParser for RevocationDocumentParser {
- fn parse_standard(
- doc: &str,
- body: &str,
- currency: &str,
- signatures: Vec<Sig>,
- ) -> Result<V10Document, V10DocumentParsingError> {
- if let Some(caps) = REVOCATION_REGEX.captures(body) {
+impl TextDocumentParser for RevocationDocumentParser {
+ fn parse(doc: &str, currency: &str) -> Result<V10Document, V10DocumentParsingError> {
+ match DocumentsParser::parse(Rule::revoc, doc) {
+ Ok(mut doc_ast) => {
+ let revoc_ast = doc_ast.next().unwrap(); // get and unwrap the `revoc` rule; never fails
+ let revoc_vx_ast = revoc_ast.into_inner().next().unwrap(); // get and unwrap the `revoc_vX` rule; never fails
+
+ match revoc_vx_ast.as_rule() {
+ Rule::revoc_v10 => {
+ let mut pubkeys = Vec::with_capacity(1);
+ let mut uid = "";
+ let mut sigs = Vec::with_capacity(2);
+ let mut blockstamps = Vec::with_capacity(1);
+ for field in revoc_vx_ast.into_inner() {
+ match field.as_rule() {
+ Rule::currency => {
+ if currency != field.as_str() {
+ return Err(V10DocumentParsingError::InvalidCurrency());
+ }
+ }
+ Rule::pubkey => {
+ if !pubkeys.is_empty() {
+ return Err(V10DocumentParsingError::InvalidInnerFormat(
+ "Revocation document must contain exactly one pubkey !",
+ ));
+ }
+ pubkeys.push(PubKey::Ed25519(
+ ed25519::PublicKey::from_base58(field.as_str()).unwrap(), // Grammar ensures that we have a base58 string.
+ ));
+ }
+ Rule::uid => {
+ uid = field.as_str();
+ }
+ Rule::blockstamp => {
+ if blockstamps.len() > 1 {
+ return Err(V10DocumentParsingError::InvalidInnerFormat(
+ "Revocation document must contain exactly one blockstamp !",
+ ));
+ }
+ let mut inner_rules = field.into_inner(); // { integer ~ "-" ~ hash }
+
+ let block_id: &str = inner_rules.next().unwrap().as_str();
+ let block_hash: &str = inner_rules.next().unwrap().as_str();
+ blockstamps.push(Blockstamp {
+ id: BlockId(block_id.parse().unwrap()), // Grammar ensures that we have a digits string.
+ hash: BlockHash(Hash::from_hex(block_hash).unwrap()), // Grammar ensures that we have an hexadecimal string.
+ });
+ }
+ Rule::ed25519_sig => {
+ sigs.push(Sig::Ed25519(
+ ed25519::Signature::from_base64(field.as_str()).unwrap(), // Grammar ensures that we have a base64 string.
+ ));
+ }
+ Rule::EOI => (),
+ _ => panic!("unexpected rule"), // Grammar ensures that we never reach this line
+ }
+ }
+ Ok(V10Document::Revocation(Box::new(RevocationDocument {
+ text: doc.to_owned(),
+ issuers: vec![pubkeys[0]],
+ currency: currency.to_owned(),
+ identity_username: uid.to_owned(),
+ identity_blockstamp: blockstamps[0],
+ identity_sig: sigs[0],
+ signatures: vec![sigs[1]],
+ })))
+ }
+ _ => Err(V10DocumentParsingError::UnexpectedVersion()),
+ }
+ }
+ Err(pest_error) => panic!("{}", pest_error), //Err(V10DocumentParsingError::PestError()),
+ }
+
+ /*if let Some(caps) = REVOCATION_REGEX.captures(body) {
let issuer = &caps["issuer"];
let identity_username = &caps["idty_uid"];
let identity_blockstamp = &caps["idty_blockstamp"];
let identity_sig = &caps["idty_sig"];
-
+
// Regex match so should not fail.
// TODO : Test it anyway
let issuer = PubKey::Ed25519(ed25519::PublicKey::from_base58(issuer).unwrap());
let identity_username = String::from(identity_username);
let identity_blockstamp = Blockstamp::from_string(identity_blockstamp).unwrap();
let identity_sig = Sig::Ed25519(Signature::from_base64(identity_sig).unwrap());
-
+
Ok(V10Document::Revocation(Box::new(RevocationDocument {
text: doc.to_owned(),
issuers: vec![issuer],
@@ -228,18 +285,16 @@ impl StandardTextDocumentParser for RevocationDocumentParser {
signatures,
})))
} else {
- Err(V10DocumentParsingError::InvalidInnerFormat(
- "Revocation".to_string(),
- ))
- }
+ Err(V10DocumentParsingError::InvalidInnerFormat("Revocation"))
+ }*/
}
}
#[cfg(test)]
mod tests {
use super::*;
- use blockchain::VerificationResult;
use duniter_crypto::keys::{PrivateKey, PublicKey, Signature};
+ use VerificationResult;
#[test]
fn generate_real_document() {
@@ -288,17 +343,6 @@ mod tests {
);
}
- #[test]
- fn revocation_standard_regex() {
- assert!(REVOCATION_REGEX.is_match(
- "Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-IdtyUniqueID: tic
-IdtyTimestamp: 98221-000000575AC04F5164F7A307CDB766139EA47DD249E4A2444F292BC8AAB408B3
-IdtySignature: DjeipIeb/RF0tpVCnVnuw6mH1iLJHIsDfPGLR90Twy3PeoaDz6Yzhc/UjLWqHCi5Y6wYajV0dNg4jQRUneVBCQ==
-"
- ));
- }
-
#[test]
fn revocation_document() {
let doc = "Version: 10
@@ -308,22 +352,11 @@ Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
IdtyUniqueID: tic
IdtyTimestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
IdtySignature: 1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==
-";
-
- let body = "Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-IdtyUniqueID: tic
-IdtyTimestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-IdtySignature: 1eubHHbuNfilHMM0G2bI30iZzebQ2cQ1PC7uPAw08FGMMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==
-";
+XXOgI++6qpY9O31ml/FcfbXCE6aixIrgkT5jL7kBle3YOMr+8wrp7Rt+z9hDVjrNfYX2gpeJsuMNfG4T/fzVDQ==";
let currency = "g1";
- let signatures = vec![Sig::Ed25519(ed25519::Signature::from_base64(
-"XXOgI++6qpY9O31ml/FcfbXCE6aixIrgkT5jL7kBle3YOMr+8wrp7Rt+z9hDVjrNfYX2gpeJsuMNfG4T/fzVDQ=="
- ).unwrap())];
-
- let doc =
- RevocationDocumentParser::parse_standard(doc, body, currency, signatures).unwrap();
+ let doc = RevocationDocumentParser::parse(doc, currency).unwrap();
if let V10Document::Revocation(doc) = doc {
println!("Doc : {:?}", doc);
assert_eq!(doc.verify_signatures(), VerificationResult::Valid())
diff --git a/documents/blockchain/v10/documents/transaction.rs b/documents/src/v10/transaction.rs
similarity index 62%
rename from documents/blockchain/v10/documents/transaction.rs
rename to documents/src/v10/transaction.rs
index 077e3350..89695260 100644
--- a/documents/blockchain/v10/documents/transaction.rs
+++ b/documents/src/v10/transaction.rs
@@ -15,44 +15,17 @@
//! Wrappers around Transaction documents.
-use blockchain::v10::documents::*;
-use blockchain::{BlockchainProtocol, Document, DocumentBuilder, IntoSpecializedDocument};
use crypto::digest::Digest;
use crypto::sha2::Sha256;
-use regex::Regex;
-use regex::RegexBuilder;
+use pest::iterators::Pair;
+use pest::iterators::Pairs;
+use pest::Parser;
use std::ops::{Add, Deref, Sub};
use std::str::FromStr;
-use {BlockId, Blockstamp, Hash};
-
-lazy_static! {
- static ref TRANSACTION_REGEX_SIZE: &'static usize = &40_000_000;
- static ref TRANSACTION_REGEX_BUILDER: &'static str =
- r"^Blockstamp: (?P<blockstamp>[0-9]+-[0-9A-F]{64})\nLocktime: (?P<locktime>[0-9]+)\nIssuers:(?P<issuers>(?:\n[1-9A-Za-z][^OIl]{43,44})+)Inputs:\n(?P<inputs>([0-9A-Za-z:]+\n)+)Unlocks:\n(?P<unlocks>([0-9]+:(SIG\([0-9]+\) ?|XHX\(\w+\) ?)+\n)+)Outputs:\n(?P<outputs>([0-9A-Za-z()&|: ]+\n)+)Comment: (?P<comment>[\\\w:/;*\[\]()?!^+=@&~#{}|<>%. -]{0,255})\n";
- static ref ISSUER_REGEX: Regex = Regex::new("(?P<issuer>[1-9A-Za-z]{43,44})\n").unwrap();
- static ref D_INPUT_REGEX: Regex = Regex::new(
- "^(?P<amount>[1-9][0-9]*):(?P<base>[0-9]+):D:(?P<pubkey>[1-9A-Za-z]{43,44}):(?P<block_number>[0-9]+)$"
- ).unwrap();
- static ref T_INPUT_REGEX: Regex = Regex::new(
- "^(?P<amount>[1-9][0-9]*):(?P<base>[0-9]+):T:(?P<tx_hash>[0-9A-F]{64}):(?P<tx_index>[0-9]+)$"
- ).unwrap();
- static ref UNLOCKS_REGEX: Regex = Regex::new(
- r"^(?P<index>[0-9]+):(?P<unlocks>(SIG\([0-9]+\) ?|XHX\(\w+\) ?)+)$"
- ).unwrap();
- static ref UNLOCK_SIG_REGEX: Regex =
- Regex::new(r"^SIG\((?P<index>[0-9]+)\)$").unwrap();
- static ref UNLOCK_XHX_REGEX: Regex = Regex::new(r"^XHX\((?P<code>\w+)\)$").unwrap();
- static ref OUTPUT_COND_SIG_REGEX: Regex = Regex::new(r"^SIG\((?P<pubkey>[1-9A-Za-z]{43,44})\)*$").unwrap();
- static ref OUTPUT_COND_XHX_REGEX: Regex = Regex::new(r"^XHX\((?P<hash>[0-9A-F]{64})\)*$").unwrap();
- static ref OUTPUT_COND_CLTV_REGEX: Regex = Regex::new(r"^CLTV\((?P<timestamp>[0-9]+)\)*$").unwrap();
- static ref OUTPUT_COND_CSV_REGEX: Regex = Regex::new(r"^CSV\((?P<duration>[0-9]+)\)*$").unwrap();
- static ref OUPUT_CONDS_BRAKETS: Regex = Regex::new(r"^\((?P<conditions>[0-9A-Za-z()&| ]+)\)$").unwrap();
- static ref OUPUT_CONDS_AND: Regex = Regex::new(r"^(?P<conditions_group_1>[0-9A-Za-z()&| ]+) && (?P<conditions_group_2>[0-9A-Za-z()&| ]+)$").unwrap();
- static ref OUPUT_CONDS_OR: Regex = Regex::new(r"^(?P<conditions_group_1>[0-9A-Za-z()&| ]+) \|\| (?P<conditions_group_2>[0-9A-Za-z()&| ]+)$").unwrap();
- static ref OUTPUT_REGEX: Regex = Regex::new(
- "^(?P<amount>[1-9][0-9]*):(?P<base>[0-9]+):(?P<conditions>[0-9A-Za-z()&| ]+)$"
- ).unwrap();
-}
+
+use blockstamp::Blockstamp;
+use v10::*;
+use *;
/// Wrap a transaction amount
#[derive(Debug, Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Deserialize, Hash, Serialize)]
@@ -103,8 +76,55 @@ impl ToString for TransactionInput {
}
impl TransactionInput {
+ fn from_pest_pairs(mut pairs: Pairs<Rule>) -> TransactionInput {
+ let tx_input_type_pair = pairs.next().unwrap();
+ match tx_input_type_pair.as_rule() {
+ Rule::tx_input_du => {
+ let mut inner_rules = tx_input_type_pair.into_inner(); // ${ tx_amount ~ ":" ~ tx_amount_base ~ ":D:" ~ pubkey ~ ":" ~ du_block_id }
+
+ TransactionInput::D(
+ TxAmount(inner_rules.next().unwrap().as_str().parse().unwrap()),
+ TxBase(inner_rules.next().unwrap().as_str().parse().unwrap()),
+ PubKey::Ed25519(
+ ed25519::PublicKey::from_base58(inner_rules.next().unwrap().as_str())
+ .unwrap(),
+ ),
+ BlockId(inner_rules.next().unwrap().as_str().parse().unwrap()),
+ )
+ }
+ Rule::tx_input_tx => {
+ let mut inner_rules = tx_input_type_pair.into_inner(); // ${ tx_amount ~ ":" ~ tx_amount_base ~ ":D:" ~ pubkey ~ ":" ~ du_block_id }
+
+ TransactionInput::T(
+ TxAmount(inner_rules.next().unwrap().as_str().parse().unwrap()),
+ TxBase(inner_rules.next().unwrap().as_str().parse().unwrap()),
+ Hash::from_hex(inner_rules.next().unwrap().as_str()).unwrap(),
+ TxIndex(inner_rules.next().unwrap().as_str().parse().unwrap()),
+ )
+ }
+ _ => panic!("unexpected rule: {:?}", tx_input_type_pair.as_rule()), // Grammar ensures that we never reach this line
+ }
+ }
+}
+
+impl FromStr for TransactionInput {
+ type Err = V10DocumentParsingError;
+
+ fn from_str(source: &str) -> Result<Self, Self::Err> {
+ match DocumentsParser::parse(Rule::tx_input, source) {
+ Ok(mut pairs) => Ok(TransactionInput::from_pest_pairs(
+ pairs.next().unwrap().into_inner(),
+ )),
+ Err(_) => Err(V10DocumentParsingError::InvalidInnerFormat(
+ "Invalid unlocks !",
+ )),
+ }
+ }
+}
+
+/*impl TransactionInput {
/// Parse Transaction Input from string.
- pub fn parse_from_str(source: &str) -> Result<TransactionInput, V10DocumentParsingError> {
+ pub fn from_str(source: &str) -> Result<TransactionInput, V10DocumentParsingError> {
if let Some(caps) = D_INPUT_REGEX.captures(source) {
let amount = &caps["amount"];
let base = &caps["base"];
@@ -136,12 +156,10 @@ impl TransactionInput {
))
} else {
println!("Fail to parse this input = {:?}", source);
- Err(V10DocumentParsingError::InvalidInnerFormat(String::from(
- "Transaction2",
- )))
+ Err(V10DocumentParsingError::InvalidInnerFormat("Transaction2"))
}
}
-}
+}*/
/// Wrap a transaction unlock proof
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
@@ -161,24 +179,6 @@ impl ToString for TransactionUnlockProof {
}
}
-impl TransactionUnlockProof {
- fn parse_from_str(source: &str) -> Result<TransactionUnlockProof, V10DocumentParsingError> {
- if let Some(caps) = UNLOCK_SIG_REGEX.captures(source) {
- let index = &caps["index"];
- Ok(TransactionUnlockProof::Sig(
- index.parse().expect("fail to parse SIG unlock"),
- ))
- } else if let Some(caps) = UNLOCK_XHX_REGEX.captures(source) {
- let code = &caps["code"];
- Ok(TransactionUnlockProof::Xhx(String::from(code)))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(String::from(
- "Transaction3",
- )))
- }
- }
-}
-
/// Wrap a transaction unlocks input
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct TransactionInputUnlocks {
@@ -201,28 +201,46 @@ impl ToString for TransactionInputUnlocks {
}
impl TransactionInputUnlocks {
- /// Parse Transaction Unlock from string.
- pub fn parse_from_str(
- source: &str,
- ) -> Result<TransactionInputUnlocks, V10DocumentParsingError> {
- if let Some(caps) = UNLOCKS_REGEX.captures(source) {
- let index = &caps["index"].parse().expect("fail to parse unlock index");
- let unlocks = &caps["unlocks"];
-
- let unlocks_array: Vec<&str> = unlocks.split(' ').collect();
- let mut unlocks = Vec::new();
- for unlock in unlocks_array {
- unlocks.push(TransactionUnlockProof::parse_from_str(unlock)?);
+ fn from_pest_pairs(pairs: Pairs<Rule>) -> TransactionInputUnlocks {
+ let mut input_index = 0;
+ let mut unlock_conds = Vec::new();
+ for unlock_field in pairs {
+ // ${ input_index ~ ":" ~ unlock_cond ~ (" " ~ unlock_cond)* }
+ match unlock_field.as_rule() {
+ Rule::input_index => input_index = unlock_field.as_str().parse().unwrap(),
+ Rule::unlock_sig => unlock_conds.push(TransactionUnlockProof::Sig(
+ unlock_field
+ .into_inner()
+ .next()
+ .unwrap()
+ .as_str()
+ .parse()
+ .unwrap(),
+ )),
+ Rule::unlock_xhx => unlock_conds.push(TransactionUnlockProof::Xhx(String::from(
+ unlock_field.into_inner().next().unwrap().as_str(),
+ ))),
+ _ => panic!("unexpected rule: {:?}", unlock_field.as_rule()), // Grammar ensures that we never reach this line
}
- Ok(TransactionInputUnlocks {
- index: *index,
- unlocks,
- })
- } else {
- println!("Fail to parse this unlock = {:?}", source);
- Err(V10DocumentParsingError::InvalidInnerFormat(String::from(
- "Transaction4",
- )))
+ }
+ TransactionInputUnlocks {
+ index: input_index,
+ unlocks: unlock_conds,
+ }
+ }
+}
+
+impl FromStr for TransactionInputUnlocks {
+ type Err = V10DocumentParsingError;
+
+ fn from_str(source: &str) -> Result<Self, Self::Err> {
+ match DocumentsParser::parse(Rule::tx_unlock, source) {
+ Ok(mut pairs) => Ok(TransactionInputUnlocks::from_pest_pairs(
+ pairs.next().unwrap().into_inner(),
+ )),
+ Err(_) => Err(V10DocumentParsingError::InvalidInnerFormat(
+ "Invalid unlocks !",
+ )),
}
}
}
@@ -251,48 +269,6 @@ impl ToString for TransactionOutputCondition {
}
}
-impl TransactionOutputCondition {
- fn parse_from_str(source: &str) -> Result<TransactionOutputCondition, V10DocumentParsingError> {
- if let Some(caps) = OUTPUT_COND_SIG_REGEX.captures(source) {
- if let Ok(pubkey) = ed25519::PublicKey::from_base58(&caps["pubkey"]) {
- Ok(TransactionOutputCondition::Sig(PubKey::Ed25519(pubkey)))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(String::from(
- "OutputCondition : Fail to parse SIG pubkey.",
- )))
- }
- } else if let Some(caps) = OUTPUT_COND_XHX_REGEX.captures(source) {
- if let Ok(hash) = Hash::from_hex(&caps["hash"]) {
- Ok(TransactionOutputCondition::Xhx(hash))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(String::from(
- "OutputCondition : Fail to parse XHX Hash.",
- )))
- }
- } else if let Some(caps) = OUTPUT_COND_CLTV_REGEX.captures(source) {
- if let Ok(timestamp) = caps["timestamp"].parse() {
- Ok(TransactionOutputCondition::Cltv(timestamp))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(String::from(
- "OutputCondition : Fail to parse CLTV timestamp.",
- )))
- }
- } else if let Some(caps) = OUTPUT_COND_CSV_REGEX.captures(source) {
- if let Ok(duration) = caps["duration"].parse() {
- Ok(TransactionOutputCondition::Csv(duration))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(String::from(
- "OutputCondition : Fail to parse CSV duraion.",
- )))
- }
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(
- "Transaction5".to_string(),
- ))
- }
- }
-}
-
/// Wrap an utxo conditions
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct UTXOConditions {
@@ -329,17 +305,6 @@ impl ToString for UTXOConditions {
}
}
-impl ::std::str::FromStr for UTXOConditions {
- type Err = V10DocumentParsingError;
-
- fn from_str(source: &str) -> Result<Self, Self::Err> {
- Ok(UTXOConditions {
- origin_str: Some(String::from(source)),
- conditions: UTXOConditionsGroup::from_str(source)?,
- })
- }
-}
-
/// Wrap a transaction ouput condition group
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub enum UTXOConditionsGroup {
@@ -353,6 +318,79 @@ pub enum UTXOConditionsGroup {
Or(Box<UTXOConditionsGroup>, Box<UTXOConditionsGroup>),
}
+macro_rules! utxo_conds_wrap_op_chain {
+ ($op:expr, $fn_name:ident) => {
+ fn $fn_name(conds_subgroups: &mut Vec<UTXOConditionsGroup>) -> UTXOConditionsGroup {
+ if conds_subgroups.len() == 2 {
+ $op(
+ Box::new(conds_subgroups[0].clone()),
+ Box::new(conds_subgroups[1].clone()),
+ )
+ } else if conds_subgroups.len() > 2 {
+ let last_subgroup = conds_subgroups.pop().unwrap();
+ let previous_last_subgroup = conds_subgroups.pop().unwrap();
+ conds_subgroups.push($op(
+ Box::new(previous_last_subgroup),
+ Box::new(last_subgroup),
+ ));
+ UTXOConditionsGroup::$fn_name(conds_subgroups)
+ } else {
+ panic!(
+ "Grammar should ensure that and chain contains at least two conditions subgroups !"
+ )
+ }
+ }
+ }
+}
+
+impl UTXOConditionsGroup {
+ /// Wrap UTXO and chain
+ utxo_conds_wrap_op_chain!(UTXOConditionsGroup::And, new_and_chain);
+ /// Wrap UTXO or chain
+ utxo_conds_wrap_op_chain!(UTXOConditionsGroup::Or, new_or_chain);
+
+ /// Wrap UTXO conditions
+ pub fn wrap_utxo_conds(pair: Pair<Rule>) -> UTXOConditionsGroup {
+ match pair.as_rule() {
+ Rule::output_and_group => {
+ let mut and_pairs = pair.into_inner();
+ let mut conds_subgroups: Vec<UTXOConditionsGroup> = and_pairs
+ .map(UTXOConditionsGroup::wrap_utxo_conds)
+ .collect();
+ UTXOConditionsGroup::Brackets(Box::new(UTXOConditionsGroup::new_and_chain(
+ &mut conds_subgroups,
+ )))
+ }
+ Rule::output_or_group => {
+ let mut or_pairs = pair.into_inner();
+ let mut conds_subgroups: Vec<UTXOConditionsGroup> =
+ or_pairs.map(UTXOConditionsGroup::wrap_utxo_conds).collect();
+ UTXOConditionsGroup::Brackets(Box::new(UTXOConditionsGroup::new_or_chain(
+ &mut conds_subgroups,
+ )))
+ }
+ Rule::output_cond_sig => {
+ UTXOConditionsGroup::Single(TransactionOutputCondition::Sig(PubKey::Ed25519(
+ ed25519::PublicKey::from_base58(pair.into_inner().next().unwrap().as_str())
+ .unwrap(),
+ )))
+ }
+ Rule::output_cond_xhx => UTXOConditionsGroup::Single(TransactionOutputCondition::Xhx(
+ Hash::from_hex(pair.into_inner().next().unwrap().as_str()).unwrap(),
+ )),
+ Rule::output_cond_csv => UTXOConditionsGroup::Single(TransactionOutputCondition::Csv(
+ pair.into_inner().next().unwrap().as_str().parse().unwrap(),
+ )),
+ Rule::output_cond_cltv => {
+ UTXOConditionsGroup::Single(TransactionOutputCondition::Cltv(
+ pair.into_inner().next().unwrap().as_str().parse().unwrap(),
+ ))
+ }
+ _ => panic!("unexpected rule: {:?}", pair.as_rule()), // Grammar ensures that we never reach this line
+ }
+ }
+}
+
impl ToString for UTXOConditionsGroup {
fn to_string(&self) -> String {
match *self {
@@ -374,38 +412,6 @@ impl ToString for UTXOConditionsGroup {
}
}
-impl ::std::str::FromStr for UTXOConditionsGroup {
- type Err = V10DocumentParsingError;
-
- fn from_str(conditions: &str) -> Result<Self, Self::Err> {
- if let Ok(single_condition) = TransactionOutputCondition::parse_from_str(conditions) {
- Ok(UTXOConditionsGroup::Single(single_condition))
- } else if let Some(caps) = OUPUT_CONDS_BRAKETS.captures(conditions) {
- let inner_conditions = UTXOConditionsGroup::from_str(&caps["conditions"])?;
- Ok(UTXOConditionsGroup::Brackets(Box::new(inner_conditions)))
- } else if let Some(caps) = OUPUT_CONDS_AND.captures(conditions) {
- let conditions_group_1 = UTXOConditionsGroup::from_str(&caps["conditions_group_1"])?;
- let conditions_group_2 = UTXOConditionsGroup::from_str(&caps["conditions_group_2"])?;
- Ok(UTXOConditionsGroup::And(
- Box::new(conditions_group_1),
- Box::new(conditions_group_2),
- ))
- } else if let Some(caps) = OUPUT_CONDS_OR.captures(conditions) {
- let conditions_group_1 = UTXOConditionsGroup::from_str(&caps["conditions_group_1"])?;
- let conditions_group_2 = UTXOConditionsGroup::from_str(&caps["conditions_group_2"])?;
- Ok(UTXOConditionsGroup::Or(
- Box::new(conditions_group_1),
- Box::new(conditions_group_2),
- ))
- } else {
- println!("fail to parse this output condition = {:?}", conditions);
- Err(V10DocumentParsingError::InvalidInnerFormat(String::from(
- "Transaction6",
- )))
- }
- }
-}
-
/// Wrap a transaction ouput
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct TransactionOutput {
@@ -440,21 +446,33 @@ impl ToString for TransactionOutput {
}
impl TransactionOutput {
- /// Parse Transaction Output from string.
- pub fn parse_from_str(source: &str) -> Result<TransactionOutput, V10DocumentParsingError> {
- if let Some(caps) = OUTPUT_REGEX.captures(source) {
- let amount = TxAmount(caps["amount"].parse().expect("fail to parse output amount"));
- let base = TxBase(caps["base"].parse().expect("fail to parse base amount"));
- let conditions = UTXOConditions::from_str(&caps["conditions"])?;
- Ok(TransactionOutput {
- conditions,
- amount,
- base,
- })
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(
- "Transaction7".to_string(),
- ))
+ fn from_pest_pairs(mut utxo_pairs: Pairs<Rule>) -> TransactionOutput {
+ let amount = TxAmount(utxo_pairs.next().unwrap().as_str().parse().unwrap());
+ let base = TxBase(utxo_pairs.next().unwrap().as_str().parse().unwrap());
+ let conditions_pairs = utxo_pairs.next().unwrap();
+ let conditions_origin_str = conditions_pairs.as_str();
+ TransactionOutput {
+ amount,
+ base,
+ conditions: UTXOConditions {
+ origin_str: Some(String::from(conditions_origin_str)),
+ conditions: UTXOConditionsGroup::wrap_utxo_conds(conditions_pairs),
+ },
+ }
+ }
+}
+
+impl FromStr for TransactionOutput {
+ type Err = V10DocumentParsingError;
+
+ fn from_str(source: &str) -> Result<Self, Self::Err> {
+ match DocumentsParser::parse(Rule::tx_output, source) {
+ Ok(mut utxo_pairs) => Ok(TransactionOutput::from_pest_pairs(
+ utxo_pairs.next().unwrap().into_inner(),
+ )),
+ Err(_) => Err(V10DocumentParsingError::InvalidInnerFormat(
+ "Invalid output !",
+ )),
}
}
}
@@ -563,7 +581,7 @@ impl Document for TransactionDocument {
}
fn as_bytes(&self) -> &[u8] {
- self.as_text().as_bytes()
+ self.as_text_without_signature().as_bytes()
}
}
@@ -743,72 +761,80 @@ Issuers:
#[derive(Debug, Clone, Copy)]
pub struct TransactionDocumentParser;
-impl StandardTextDocumentParser for TransactionDocumentParser {
- fn parse_standard(
- doc: &str,
- body: &str,
- currency: &str,
- signatures: Vec<Sig>,
- ) -> Result<V10Document, V10DocumentParsingError> {
- let tx_regex: Regex = RegexBuilder::new(&TRANSACTION_REGEX_BUILDER)
- .size_limit(**TRANSACTION_REGEX_SIZE)
- .build()
- .expect("fail to build TRANSACTION_REGEX !");
- if let Some(caps) = tx_regex.captures(body) {
- let blockstamp =
- Blockstamp::from_string(&caps["blockstamp"]).expect("fail to parse blockstamp");
- let locktime = caps["locktime"].parse().expect("fail to parse locktime");
- let issuers_str = &caps["issuers"];
- let inputs = &caps["inputs"];
- let unlocks = &caps["unlocks"];
- let outputs = &caps["outputs"];
- let comment = String::from(&caps["comment"]);
-
- let mut issuers = Vec::new();
- for caps in ISSUER_REGEX.captures_iter(issuers_str) {
- issuers.push(PubKey::Ed25519(
- ed25519::PublicKey::from_base58(&caps["issuer"]).expect("fail to parse issuer"),
- ));
- }
- let inputs_array: Vec<&str> = inputs.split('\n').collect();
- let mut inputs = Vec::new();
- for input in inputs_array {
- if !input.is_empty() {
- inputs.push(TransactionInput::parse_from_str(input)?);
- }
- }
- let unlocks_array: Vec<&str> = unlocks.split('\n').collect();
- let mut unlocks = Vec::new();
- for unlock in unlocks_array {
- if !unlock.is_empty() {
- unlocks.push(TransactionInputUnlocks::parse_from_str(unlock)?);
+impl TextDocumentParser for TransactionDocumentParser {
+ fn parse(doc: &str, currency: &str) -> Result<V10Document, V10DocumentParsingError> {
+ match DocumentsParser::parse(Rule::tx, doc) {
+ Ok(mut doc_ast) => {
+ let tx_ast = doc_ast.next().unwrap(); // get and unwrap the `tx` rule; never fails
+ let tx_vx_ast = tx_ast.into_inner().next().unwrap(); // get and unwrap the `tx_vX` rule; never fails
+
+ match tx_vx_ast.as_rule() {
+ Rule::tx_v10 => {
+ let mut blockstamp = Blockstamp::default();
+ let mut locktime = 0;
+ let mut issuers = Vec::new();
+ let mut inputs = Vec::new();
+ let mut unlocks = Vec::new();
+ let mut outputs = Vec::new();
+ let mut comment = "";
+ let mut sigs = Vec::new();
+
+ for field in tx_vx_ast.into_inner() {
+ match field.as_rule() {
+ Rule::currency => {
+ if currency != field.as_str() {
+ return Err(V10DocumentParsingError::InvalidCurrency());
+ }
+ }
+ Rule::blockstamp => {
+ let mut inner_rules = field.into_inner(); // ${ block_id ~ "-" ~ hash }
+
+ let block_id: &str = inner_rules.next().unwrap().as_str();
+ let block_hash: &str = inner_rules.next().unwrap().as_str();
+ blockstamp = Blockstamp {
+ id: BlockId(block_id.parse().unwrap()), // Grammar ensures that we have a digits string.
+ hash: BlockHash(Hash::from_hex(block_hash).unwrap()), // Grammar ensures that we have an hexadecimal string.
+ };
+ }
+ Rule::tx_locktime => locktime = field.as_str().parse().unwrap(), // Grammar ensures that we have digits characters.
+ Rule::pubkey => issuers.push(PubKey::Ed25519(
+ ed25519::PublicKey::from_base58(field.as_str()).unwrap(), // Grammar ensures that we have a base58 string.
+ )),
+ Rule::tx_input => inputs
+ .push(TransactionInput::from_pest_pairs(field.into_inner())),
+ Rule::tx_unlock => unlocks.push(
+ TransactionInputUnlocks::from_pest_pairs(field.into_inner()),
+ ),
+ Rule::tx_output => outputs
+ .push(TransactionOutput::from_pest_pairs(field.into_inner())),
+ Rule::tx_comment => comment = field.as_str(),
+ Rule::ed25519_sig => {
+ sigs.push(Sig::Ed25519(
+ ed25519::Signature::from_base64(field.as_str()).unwrap(), // Grammar ensures that we have a base64 string.
+ ));
+ }
+ Rule::EOI => (),
+ _ => panic!("unexpected rule: {:?}", field.as_rule()), // Grammar ensures that we never reach this line
+ }
+ }
+ Ok(V10Document::Transaction(Box::new(TransactionDocument {
+ text: Some(doc.to_owned()),
+ currency: currency.to_owned(),
+ blockstamp,
+ locktime,
+ issuers,
+ inputs,
+ unlocks,
+ outputs,
+ comment: comment.to_owned(),
+ signatures: sigs,
+ hash: None,
+ })))
+ }
+ _ => Err(V10DocumentParsingError::UnexpectedVersion()),
}
}
- let outputs_array: Vec<&str> = outputs.split('\n').collect();
- let mut outputs = Vec::new();
- for output in outputs_array {
- if !output.is_empty() {
- outputs.push(TransactionOutput::parse_from_str(output)?);
- }
- }
-
- Ok(V10Document::Transaction(Box::new(TransactionDocument {
- text: Some(doc.to_owned()),
- currency: currency.to_owned(),
- blockstamp,
- locktime,
- issuers,
- inputs,
- unlocks,
- outputs,
- comment,
- signatures,
- hash: None,
- })))
- } else {
- Err(V10DocumentParsingError::InvalidInnerFormat(
- "Transaction1".to_string(),
- ))
+ Err(pest_error) => panic!("{}", pest_error), //Err(V10DocumentParsingError::PestError()),
}
}
}
@@ -816,7 +842,7 @@ impl StandardTextDocumentParser for TransactionDocumentParser {
#[cfg(test)]
mod tests {
use super::*;
- use blockchain::{Document, VerificationResult};
+ use {Document, VerificationResult};
#[test]
fn generate_real_document() {
@@ -847,13 +873,20 @@ mod tests {
blockstamp: &block,
locktime: &0,
issuers: &vec![pubkey],
- inputs: &vec![TransactionInput::parse_from_str(
- "10:0:D:DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:0",
- )
- .expect("fail to parse input !")],
- unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)")
- .expect("fail to parse unlock !")],
- outputs: &vec![TransactionOutput::parse_from_str(
+ inputs: &vec![TransactionInput::D(
+ TxAmount(10),
+ TxBase(0),
+ PubKey::Ed25519(
+ ed25519::PublicKey::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV")
+ .unwrap(),
+ ),
+ BlockId(0),
+ )],
+ unlocks: &vec![TransactionInputUnlocks {
+ index: 0,
+ unlocks: vec![TransactionUnlockProof::Sig(0)],
+ }],
+ outputs: &vec![TransactionOutput::from_str(
"10:0:SIG(FD9wujR7KABw88RyKEGBYRLz8PA6jzVCbcBAsrBXBqSa)",
)
.expect("fail to parse output !")],
@@ -895,18 +928,22 @@ mod tests {
blockstamp: &block,
locktime: &0,
issuers: &vec![pubkey],
- inputs: &vec![TransactionInput::parse_from_str(
- "950:0:T:2CF1ACD8FE8DC93EE39A1D55881C50D87C55892AE8E4DB71D4EBAB3D412AA8FD:1",
- )
- .expect("fail to parse input !")],
- unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)")
- .expect("fail to parse unlock !")],
+ inputs: &vec![TransactionInput::T(
+ TxAmount(950),
+ TxBase(0),
+ Hash::from_hex("2CF1ACD8FE8DC93EE39A1D55881C50D87C55892AE8E4DB71D4EBAB3D412AA8FD")
+ .unwrap(),
+ TxIndex(1),
+ )],
+ unlocks: &vec![
+ TransactionInputUnlocks::from_str("0:SIG(0)").expect("fail to parse unlock !")
+ ],
outputs: &vec![
- TransactionOutput::parse_from_str(
+ TransactionOutput::from_str(
"30:0:SIG(38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE)",
)
.expect("fail to parse output !"),
- TransactionOutput::parse_from_str(
+ TransactionOutput::from_str(
"920:0:SIG(FEkbc4BfJukSWnCU6Hed6dgwwTuPFTVdgz5LpL4iHr9J)",
)
.expect("fail to parse output !"),
@@ -924,42 +961,6 @@ mod tests {
);
}
- #[test]
- fn transaction_standard_regex() {
- let tx_regex: Regex = RegexBuilder::new(&TRANSACTION_REGEX_BUILDER)
- .size_limit(**TRANSACTION_REGEX_SIZE)
- .build()
- .expect("fail to build TRANSACTION_REGEX !");
- assert!(tx_regex.is_match(
- "Blockstamp: 204-00003E2B8A35370BA5A7064598F628A62D4E9EC1936BE8651CE9A85F2E06981B
-Locktime: 0
-Issuers:
-HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY
-CYYjHsNyg3HMRMpTHqCJAN9McjH5BwFLmDKGV3PmCuKp
-FD9wujR7KABw88RyKEGBYRLz8PA6jzVCbcBAsrBXBqSa
-Inputs:
-40:2:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
-70:2:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
-20:2:D:HsLShAtzXTVxeUtQd7yi5Z5Zh4zNvbu8sTEZ53nfKcqY:46
-70:2:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
-20:2:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
-15:2:D:FD9wujR7KABw88RyKEGBYRLz8PA6jzVCbcBAsrBXBqSa:46
-Unlocks:
-0:SIG(0)
-1:XHX(7665798292)
-2:SIG(0)
-3:SIG(0) SIG(2)
-4:SIG(0) SIG(1) SIG(2)
-5:SIG(2)
-Outputs:
-120:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
-146:2:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)
-49:2:(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85))
-Comment: -----@@@----- (why not this comment?)
-"
- ));
- }
-
#[test]
fn parse_transaction_document() {
let doc = "Version: 10
@@ -990,51 +991,13 @@ Outputs:
146:2:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)
49:2:(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85F2AC2FD3FA4FDC46A4FC01CA))
Comment: -----@@@----- (why not this comment?)
-";
-
- let body =
- "Blockstamp: 204-00003E2B8A35370BA5A7064598F628A62D4E9EC1936BE8651CE9A85F2E06981B
-Locktime: 0
-Issuers:
-DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-4tNQ7d9pj2Da5wUVoW9mFn7JjuPoowF977au8DdhEjVR
-FD9wujR7KABw88RyKEGBYRLz8PA6jzVCbcBAsrBXBqSa
-Inputs:
-40:2:T:6991C993631BED4733972ED7538E41CCC33660F554E3C51963E2A0AC4D6453D3:2
-70:2:T:3A09A20E9014110FD224889F13357BAB4EC78A72F95CA03394D8CCA2936A7435:8
-20:2:D:DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV:46
-70:2:T:A0D9B4CDC113ECE1145C5525873821398890AE842F4B318BD076095A23E70956:3
-20:2:T:67F2045B5318777CC52CD38B424F3E40DDA823FA0364625F124BABE0030E7B5B:5
-15:2:D:FD9wujR7KABw88RyKEGBYRLz8PA6jzVCbcBAsrBXBqSa:46
-Unlocks:
-0:SIG(0)
-1:XHX(7665798292)
-2:SIG(0)
-3:SIG(0) SIG(2)
-4:SIG(0) SIG(1) SIG(2)
-5:SIG(2)
-Outputs:
-120:2:SIG(BYfWYFrsyjpvpFysgu19rGK3VHBkz4MqmQbNyEuVU64g)
-146:2:SIG(DSz4rgncXCytsUMW2JU2yhLquZECD2XpEkpP9gG5HyAx)
-49:2:(SIG(6DyGr5LFtFmbaJYRvcs9WmBsr4cbJbJ1EV9zBbqG7A6i) || XHX(3EB4702F2AC2FD3FA4FDC46A4FC05AE8CDEE1A85F2AC2FD3FA4FDC46A4FC01CA))
-Comment: -----@@@----- (why not this comment?)
-";
+kL59C1izKjcRN429AlKdshwhWbasvyL7sthI757zm1DfZTdTIctDWlKbYeG/tS7QyAgI3gcfrTHPhu1E1lKCBw==
+e3LpgB2RZ/E/BCxPJsn+TDDyxGYzrIsMyDt//KhJCjIQD6pNUxr5M5jrq2OwQZgwmz91YcmoQ2XRQAUDpe4BAw==
+w69bYgiQxDmCReB0Dugt9BstXlAKnwJkKCdWvCeZ9KnUCv0FJys6klzYk/O/b9t74tYhWZSX0bhETWHiwfpWBw==";
let currency = "duniter_unit_test_currency";
- let signatures = vec![
- Sig::Ed25519(ed25519::Signature::from_base64(
-"kL59C1izKjcRN429AlKdshwhWbasvyL7sthI757zm1DfZTdTIctDWlKbYeG/tS7QyAgI3gcfrTHPhu1E1lKCBw=="
- ).expect("fail to parse test signature")),
- Sig::Ed25519(ed25519::Signature::from_base64(
-"e3LpgB2RZ/E/BCxPJsn+TDDyxGYzrIsMyDt//KhJCjIQD6pNUxr5M5jrq2OwQZgwmz91YcmoQ2XRQAUDpe4BAw=="
- ).expect("fail to parse test signature")),
- Sig::Ed25519(ed25519::Signature::from_base64(
-"w69bYgiQxDmCReB0Dugt9BstXlAKnwJkKCdWvCeZ9KnUCv0FJys6klzYk/O/b9t74tYhWZSX0bhETWHiwfpWBw=="
- ).expect("fail to parse test signature")),
- ];
-
- let doc = TransactionDocumentParser::parse_standard(doc, body, currency, signatures)
+ let doc = TransactionDocumentParser::parse(doc, currency)
.expect("fail to parse test transaction document !");
if let V10Document::Transaction(doc) = doc {
//println!("Doc : {:?}", doc);
diff --git a/message/lib.rs b/message/lib.rs
index d8bf3a8b..b6d75d48 100644
--- a/message/lib.rs
+++ b/message/lib.rs
@@ -41,8 +41,8 @@ use duniter_crypto::hashs::Hash;
use duniter_crypto::keys::Sig;
use duniter_dal::dal_event::DALEvent;
use duniter_dal::dal_requests::{DALRequest, DALResponse};
-use duniter_documents::blockchain::BlockchainProtocol;
use duniter_documents::BlockId;
+use duniter_documents::BlockchainProtocol;
use duniter_module::*;
use duniter_network::{NetworkEvent, NetworkResponse, OldNetworkRequest};
diff --git a/network/lib.rs b/network/lib.rs
index 4a0ed49c..b8de326f 100644
--- a/network/lib.rs
+++ b/network/lib.rs
@@ -55,12 +55,14 @@ use crypto::digest::Digest;
use crypto::sha2::Sha256;
use duniter_crypto::hashs::*;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::{
- BlockDocument, CertificationDocument, IdentityDocument, MembershipDocument, RevocationDocument,
- TransactionDocument,
-};
-use duniter_documents::blockchain::Document;
-use duniter_documents::{BlockHash, BlockId, Blockstamp};
+use duniter_documents::v10::block::BlockDocument;
+use duniter_documents::v10::certification::CertificationDocument;
+use duniter_documents::v10::identity::IdentityDocument;
+use duniter_documents::v10::membership::MembershipDocument;
+use duniter_documents::v10::revocation::RevocationDocument;
+use duniter_documents::v10::transaction::TransactionDocument;
+use duniter_documents::Document;
+use duniter_documents::{blockstamp::Blockstamp, BlockHash, BlockId};
use duniter_module::*;
use network_endpoint::ApiFeatures;
use network_head::NetworkHead;
diff --git a/network/network_head.rs b/network/network_head.rs
index 92298951..9c5d1c02 100644
--- a/network/network_head.rs
+++ b/network/network_head.rs
@@ -16,8 +16,7 @@
//! Module defining the format of network heads and how to handle them.
use duniter_crypto::keys::*;
-use duniter_documents::BlockUIdParseError;
-use duniter_documents::Blockstamp;
+use duniter_documents::blockstamp::*;
use network_head_v2::*;
use network_head_v3::*;
use serde_json;
@@ -52,8 +51,8 @@ pub enum NetworkHeadParseErr {
BaseConvertionError(BaseConvertionError),
/// ParseIntError
ParseIntError(ParseIntError),
- /// BlockUIdParseError
- BlockUIdParseError(BlockUIdParseError),
+ /// BlockstampParseError
+ BlockstampParseError(BlockstampParseError),
/// NetworkHeadMessageParseErr
NetworkHeadMessageParseErr(NetworkHeadMessageParseErr),
/// InvalidMessageVersion
@@ -78,9 +77,9 @@ impl From<BaseConvertionError> for NetworkHeadParseErr {
}
}
-impl From<BlockUIdParseError> for NetworkHeadParseErr {
- fn from(e: BlockUIdParseError) -> Self {
- NetworkHeadParseErr::BlockUIdParseError(e)
+impl From<BlockstampParseError> for NetworkHeadParseErr {
+ fn from(e: BlockstampParseError) -> Self {
+ NetworkHeadParseErr::BlockstampParseError(e)
}
}
diff --git a/network/network_head_v2.rs b/network/network_head_v2.rs
index 25fa81c1..bae01eac 100644
--- a/network/network_head_v2.rs
+++ b/network/network_head_v2.rs
@@ -16,8 +16,7 @@
//! Module defining the format of network heads v2 and how to handle them.
use duniter_crypto::keys::*;
-use duniter_documents::BlockUIdParseError;
-use duniter_documents::Blockstamp;
+use duniter_documents::blockstamp::*;
use std::cmp::Ordering;
use std::num::ParseIntError;
use std::ops::Deref;
@@ -145,8 +144,8 @@ pub enum NetworkHeadMessageParseErr {
BaseConvertionError(BaseConvertionError),
/// ParseIntError
ParseIntError(ParseIntError),
- /// BlockUIdParseError
- BlockUIdParseError(BlockUIdParseError),
+ /// BlockstampParseError
+ BlockstampParseError(BlockstampParseError),
}
impl From<BaseConvertionError> for NetworkHeadMessageParseErr {
@@ -155,9 +154,9 @@ impl From<BaseConvertionError> for NetworkHeadMessageParseErr {
}
}
-impl From<BlockUIdParseError> for NetworkHeadMessageParseErr {
- fn from(e: BlockUIdParseError) -> Self {
- NetworkHeadMessageParseErr::BlockUIdParseError(e)
+impl From<BlockstampParseError> for NetworkHeadMessageParseErr {
+ fn from(e: BlockstampParseError) -> Self {
+ NetworkHeadMessageParseErr::BlockstampParseError(e)
}
}
diff --git a/network/network_head_v3.rs b/network/network_head_v3.rs
index b227b94b..611c9807 100644
--- a/network/network_head_v3.rs
+++ b/network/network_head_v3.rs
@@ -18,7 +18,7 @@
use base58::ToBase58;
use duniter_crypto::keys::bin_signable::BinSignable;
use duniter_crypto::keys::*;
-use duniter_documents::Blockstamp;
+use duniter_documents::blockstamp::Blockstamp;
use serde_json;
use std::cmp::Ordering;
use NodeId;
diff --git a/network/network_peer.rs b/network/network_peer.rs
index d0b7bf9f..caacd339 100644
--- a/network/network_peer.rs
+++ b/network/network_peer.rs
@@ -24,7 +24,7 @@ extern crate serde;
use base58::ToBase58;
use duniter_crypto::keys::bin_signable::BinSignable;
use duniter_crypto::keys::*;
-use duniter_documents::{Blockstamp, CurrencyName};
+use duniter_documents::{blockstamp::Blockstamp, CurrencyName};
use network_endpoint::*;
use *;
diff --git a/ws2p-messages/lib.rs b/ws2p-messages/lib.rs
index 1588f275..f3f2e9b7 100644
--- a/ws2p-messages/lib.rs
+++ b/ws2p-messages/lib.rs
@@ -58,7 +58,7 @@ mod tests {
use bincode::{deserialize, serialize};
use duniter_crypto::keys::bin_signable::BinSignable;
use duniter_crypto::keys::*;
- use duniter_documents::blockchain::v10::documents::certification::*;
+ use duniter_documents::v10::certification::*;
use duniter_documents::{Blockstamp, CurrencyName};
use duniter_network::network_endpoint::*;
use duniter_network::network_peer::*;
diff --git a/ws2p-messages/v2/payload_container.rs b/ws2p-messages/v2/payload_container.rs
index 9ff1dec5..47350287 100644
--- a/ws2p-messages/v2/payload_container.rs
+++ b/ws2p-messages/v2/payload_container.rs
@@ -19,10 +19,12 @@ use super::req_responses::WS2Pv2ReqRes;
use super::requests::WS2Pv2Request;
use super::secret_flags::WS2Pv2SecretFlagsMsg;
use duniter_crypto::hashs::Hash;
-use duniter_documents::blockchain::v10::documents::{
- BlockDocument, CertificationDocument, IdentityDocument, MembershipDocument, RevocationDocument,
- TransactionDocument,
-};
+use duniter_documents::v10::block::BlockDocument;
+use duniter_documents::v10::certification::CertificationDocument;
+use duniter_documents::v10::identity::IdentityDocument;
+use duniter_documents::v10::membership::MembershipDocument;
+use duniter_documents::v10::revocation::RevocationDocument;
+use duniter_documents::v10::transaction::TransactionDocument;
use duniter_network::network_head_v2::NetworkHeadV2;
use duniter_network::network_head_v3::NetworkHeadV3Container;
use duniter_network::network_peer::PeerCardV11;
diff --git a/ws2p-messages/v2/req_responses.rs b/ws2p-messages/v2/req_responses.rs
index ed81adbc..c4010b2f 100644
--- a/ws2p-messages/v2/req_responses.rs
+++ b/ws2p-messages/v2/req_responses.rs
@@ -14,10 +14,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use duniter_crypto::hashs::Hash;
-use duniter_documents::blockchain::v10::documents::certification::CompactCertificationDocument;
-use duniter_documents::blockchain::v10::documents::identity::CompactIdentityDocument;
-use duniter_documents::blockchain::v10::documents::membership::CompactPoolMembershipDoc;
-use duniter_documents::blockchain::v10::documents::BlockDocument;
+use duniter_documents::v10::block::BlockDocument;
+use duniter_documents::v10::certification::CompactCertificationDocument;
+use duniter_documents::v10::identity::CompactIdentityDocument;
+use duniter_documents::v10::membership::CompactPoolMembershipDoc;
use duniter_documents::Blockstamp;
use std::str;
diff --git a/ws2p-v1-legacy/lib.rs b/ws2p-v1-legacy/lib.rs
index 3e7e662f..1406c811 100644
--- a/ws2p-v1-legacy/lib.rs
+++ b/ws2p-v1-legacy/lib.rs
@@ -929,7 +929,7 @@ mod tests {
use super::parsers::blocks::parse_json_block;
use super::*;
use duniter_crypto::keys::PublicKey;
- use duniter_documents::blockchain::v10::documents::BlockDocument;
+ use duniter_documents::v10::BlockDocument;
use duniter_module::DuniterModule;
use duniter_network::network_endpoint::{EndpointEnum, NetworkEndpointApi};
use duniter_network::NetworkBlock;
diff --git a/ws2p-v1-legacy/parsers/blocks.rs b/ws2p-v1-legacy/parsers/blocks.rs
index ae3aa8dd..867e9707 100644
--- a/ws2p-v1-legacy/parsers/blocks.rs
+++ b/ws2p-v1-legacy/parsers/blocks.rs
@@ -5,9 +5,9 @@ use super::identities::parse_compact_identity;
use super::transactions::parse_transaction;
use duniter_crypto::hashs::Hash;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::block::{BlockV10Parameters, TxDocOrTxHash};
-use duniter_documents::blockchain::v10::documents::membership::*;
-use duniter_documents::blockchain::v10::documents::BlockDocument;
+use duniter_documents::v10::block::{BlockV10Parameters, TxDocOrTxHash};
+use duniter_documents::v10::membership::*;
+use duniter_documents::v10::BlockDocument;
use duniter_documents::CurrencyName;
use duniter_documents::{BlockHash, BlockId};
use duniter_network::{NetworkBlock, NetworkBlockV10};
diff --git a/ws2p-v1-legacy/parsers/identities.rs b/ws2p-v1-legacy/parsers/identities.rs
index ef623354..1d288f6d 100644
--- a/ws2p-v1-legacy/parsers/identities.rs
+++ b/ws2p-v1-legacy/parsers/identities.rs
@@ -1,10 +1,9 @@
extern crate serde_json;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::identity::IdentityDocumentBuilder;
-use duniter_documents::blockchain::v10::documents::IdentityDocument;
-use duniter_documents::blockchain::DocumentBuilder;
+use duniter_documents::v10::identity::*;
use duniter_documents::Blockstamp;
+use duniter_documents::DocumentBuilder;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum IdentityParseError {
diff --git a/ws2p-v1-legacy/parsers/memberships.rs b/ws2p-v1-legacy/parsers/memberships.rs
index a193d5e6..496a1c4b 100644
--- a/ws2p-v1-legacy/parsers/memberships.rs
+++ b/ws2p-v1-legacy/parsers/memberships.rs
@@ -1,12 +1,9 @@
extern crate serde_json;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::membership::{
- MembershipDocumentBuilder, MembershipType,
-};
-use duniter_documents::blockchain::v10::documents::MembershipDocument;
-use duniter_documents::blockchain::DocumentBuilder;
+use duniter_documents::v10::membership::*;
use duniter_documents::Blockstamp;
+use duniter_documents::DocumentBuilder;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum MembershipParseError {
diff --git a/ws2p-v1-legacy/parsers/mod.rs b/ws2p-v1-legacy/parsers/mod.rs
index decd00fa..fec21d7a 100644
--- a/ws2p-v1-legacy/parsers/mod.rs
+++ b/ws2p-v1-legacy/parsers/mod.rs
@@ -23,9 +23,10 @@ pub mod transactions;
mod tests {
use super::transactions::*;
use duniter_crypto::keys::*;
- use duniter_documents::blockchain::v10::documents::transaction::*;
- use duniter_documents::blockchain::DocumentBuilder;
+ use duniter_documents::v10::transaction::*;
use duniter_documents::Blockstamp;
+ use duniter_documents::DocumentBuilder;
+ use std::str::FromStr;
#[test]
fn parse_json_tx() {
@@ -65,15 +66,15 @@ mod tests {
ed25519::PublicKey::from_base58("51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2")
.unwrap(),
)],
- inputs: &vec![TransactionInput::parse_from_str(
+ inputs: &vec![TransactionInput::from_str(
"1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496",
)
.unwrap()],
- outputs: &vec![TransactionOutput::parse_from_str(
+ outputs: &vec![TransactionOutput::from_str(
"1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)",
)
.unwrap()],
- unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()],
+ unlocks: &vec![TransactionInputUnlocks::from_str("0:SIG(0)").unwrap()],
comment: "Merci pour la calligraphie ;) de Liam",
hash: None,
};
@@ -124,21 +125,19 @@ mod tests {
ed25519::PublicKey::from_base58("FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD")
.unwrap(),
)],
- inputs: &vec![TransactionInput::parse_from_str(
+ inputs: &vec![TransactionInput::from_str(
"1000:0:D:FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD:1",
)
.unwrap()],
outputs: &vec![
- TransactionOutput::parse_from_str(
- "3:0:SIG(7vU9BMDhN6fBuRa2iK3JRbC6pqQKb4qDMGsFcQuT5cz)",
- )
- .unwrap(),
- TransactionOutput::parse_from_str(
+ TransactionOutput::from_str("3:0:SIG(7vU9BMDhN6fBuRa2iK3JRbC6pqQKb4qDMGsFcQuT5cz)")
+ .unwrap(),
+ TransactionOutput::from_str(
"997:0:SIG(FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD)",
)
.unwrap(),
],
- unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()],
+ unlocks: &vec![TransactionInputUnlocks::from_str("0:SIG(0)").unwrap()],
comment: "Un petit cafe ;-)",
hash: None,
};
diff --git a/ws2p-v1-legacy/parsers/transactions.rs b/ws2p-v1-legacy/parsers/transactions.rs
index ff24ff9e..5f4b7005 100644
--- a/ws2p-v1-legacy/parsers/transactions.rs
+++ b/ws2p-v1-legacy/parsers/transactions.rs
@@ -3,12 +3,13 @@ extern crate serde_json;
use duniter_crypto::hashs::Hash;
use duniter_crypto::keys::*;
-use duniter_documents::blockchain::v10::documents::transaction::{
+use duniter_documents::v10::transaction::{
TransactionDocument, TransactionDocumentBuilder, TransactionInput, TransactionInputUnlocks,
TransactionOutput,
};
-use duniter_documents::blockchain::DocumentBuilder;
use duniter_documents::Blockstamp;
+use duniter_documents::DocumentBuilder;
+use std::str::FromStr;
pub fn parse_transaction(
currency: &str,
@@ -36,7 +37,7 @@ pub fn parse_transaction(
let mut inputs = Vec::with_capacity(inputs_array.len());
for input in inputs_array {
let input_str = input.as_str()?;
- match TransactionInput::parse_from_str(input_str) {
+ match TransactionInput::from_str(input_str) {
Ok(input) => inputs.push(input),
Err(_) => {
return None;
@@ -46,7 +47,7 @@ pub fn parse_transaction(
let unlocks_array = source.get("unlocks")?.as_array()?;
let mut unlocks = Vec::with_capacity(unlocks_array.len());
for unlock in unlocks_array {
- match TransactionInputUnlocks::parse_from_str(unlock.as_str()?) {
+ match TransactionInputUnlocks::from_str(unlock.as_str()?) {
Ok(unlock) => unlocks.push(unlock),
Err(_) => {
return None;
@@ -56,7 +57,7 @@ pub fn parse_transaction(
let outputs_array = source.get("outputs")?.as_array()?;
let mut outputs = Vec::with_capacity(outputs_array.len());
for output in outputs_array {
- match TransactionOutput::parse_from_str(output.as_str()?) {
+ match TransactionOutput::from_str(output.as_str()?) {
Ok(output) => outputs.push(output),
Err(_) => {
return None;
@@ -121,15 +122,15 @@ Merci pour la calligraphie ;) de Liam$\
ed25519::PublicKey::from_base58("51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2")
.unwrap(),
)],
- inputs: &vec![TransactionInput::parse_from_str(
+ inputs: &vec![TransactionInput::from_str(
"1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496",
)
.unwrap()],
- outputs: &vec![TransactionOutput::parse_from_str(
+ outputs: &vec![TransactionOutput::from_str(
"1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)",
)
.unwrap()],
- unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()],
+ unlocks: &vec![TransactionInputUnlocks::from_str("0:SIG(0)").unwrap()],
comment: "Merci pour la calligraphie ;) de Liam",
hash: None,
};
--
GitLab