Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Dunitrust
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
nodes
rust
Dunitrust
Merge requests
!155
WIP: Resolve "DUBP local validation"
Code
Review changes
Check out branch
Download
Patches
Plain diff
Expand sidebar
Closed
WIP: Resolve "DUBP local validation"
jawaka-146-dubp-local-validation
into
dev
Overview
21
Commits
12
Pipelines
0
Changes
15
Closed
jawaka
requested to merge
jawaka-146-dubp-local-validation
into
dev
6 years ago
Overview
16
Commits
12
Pipelines
0
Changes
15
Closes
#146 (closed)
0
0
Merge request reports
Compare
dev
version 15
e8c1b646
5 years ago
version 14
97894794
5 years ago
version 13
2a961baa
6 years ago
version 12
be1a336d
6 years ago
version 11
e3356f0e
6 years ago
version 10
641a2447
6 years ago
version 9
dcfcc577
6 years ago
version 8
5379d9f3
6 years ago
version 7
919bab9e
6 years ago
version 6
02ea5448
6 years ago
version 5
28d03e39
6 years ago
version 4
d0bf6712
6 years ago
version 3
c7ebcfd5
6 years ago
version 2
bfc7d775
6 years ago
version 1
b385e1df
6 years ago
dev (base)
and
version 1
latest version
e8c1b646
12 commits,
5 years ago
version 15
e8c1b646
12 commits,
5 years ago
version 14
97894794
11 commits,
5 years ago
version 13
2a961baa
11 commits,
6 years ago
version 12
be1a336d
11 commits,
6 years ago
version 11
e3356f0e
10 commits,
6 years ago
version 10
641a2447
9 commits,
6 years ago
version 9
dcfcc577
8 commits,
6 years ago
version 8
5379d9f3
6 commits,
6 years ago
version 7
919bab9e
6 commits,
6 years ago
version 6
02ea5448
5 commits,
6 years ago
version 5
28d03e39
4 commits,
6 years ago
version 4
d0bf6712
3 commits,
6 years ago
version 3
c7ebcfd5
6 commits,
6 years ago
version 2
bfc7d775
1 commit,
6 years ago
version 1
b385e1df
1 commit,
6 years ago
15 files
+
603
−
171
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
Files
15
lib/modules/blockchain/blockchain/src/dubp/check/mod.rs
+
278
−
1
View file @ b385e1df
Show full file
@@ -13,7 +13,7 @@
// 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/>.
//! Sub-module
checking if a block complies with all the rules of the
(DUBP DUniter Blockchain Protocol).
//! Sub-module
that checks and applies the content of a block according to the DUBP
(DUBP DUniter Blockchain Protocol).
pub
mod
hashs
;
@@ -25,12 +25,289 @@ use durs_blockchain_dal::*;
use
durs_wot
::
*
;
use
std
::
collections
::
HashMap
;
use
dubp_documents
::
documents
::
block
::
TxDocOrTxHash
;
use
dubp_documents
::
text_document_traits
::
CompactTextDocument
;
use
dubp_documents
::
VerificationResult
;
use
durs_common_tools
::
fatal_error
;
pub
static
ZERO_STRING
:
&
'static
str
=
"0"
;
#[derive(Debug,
Copy,
Clone)]
pub
enum
InvalidBlockError
{
NoPreviousBlock
,
VersionDecrease
,
}
#[derive(Debug,
Clone)]
pub
enum
TransactionDocumentError
{
LengthError
,
NumberSourcesError
,
UnlocksError
,
SignatureIssuerError
,
VersionError
,
SignatureCountError
,
SignaturesOrderError
,
SignatureConstructionError
,
VerificationResult
(
VerificationResult
),
}
/*
impl From<VerificationResult> for TransactionDocumentError {
fn from(err: VerificationResult) -> Self {
VerificationResult(err)
}
}
*/
#[derive(Debug,
Clone)]
pub
enum
LocalVerifyBlockError
{
VerifyBlockHashsError
,
VersionBlockError
,
PreviousIssuerRootBlockError
,
ParametersRootBlockError
,
UniversalDividendRootBlockError
,
UnitBaseRootBlockError
,
BlockTimeError
,
ZerosHashBlockError
,
SignaturesLenBlockError
,
SignatureBlockError
,
SignatureMembershipDocumentError
,
SignatureRevocationDocumentError
,
TextDocumentFormat
,
TransactionDocumentError
(
TransactionDocumentError
),
}
impl
From
<
TransactionDocumentError
>
for
LocalVerifyBlockError
{
fn
from
(
err
:
TransactionDocumentError
)
->
Self
{
TransactionDocumentError
(
err
)
}
}
use
crate
::
dubp
::
check
::
LocalVerifyBlockError
::
*
;
use
crate
::
dubp
::
check
::
TransactionDocumentError
::
*
;
pub
fn
local_verification
(
block
:
&
BlockDocument
)
->
Result
<
(),
LocalVerifyBlockError
>
{
// Version
if
!
(
block
.version
==
10
||
block
.version
==
11
)
{
return
Err
(
VersionBlockError
);
}
// InnerHash
if
!
block
.verify_inner_hash
()
{
return
Err
(
VerifyBlockHashsError
);
}
// Nonce
// nothing to do
// Proof of work
if
let
Some
(
h
)
=
block
.hash
{
let
hash_string
=
h
.0
.to_hex
();
let
remainder
=
block
.pow_min
%
16
;
let
nb_zeros
=
(
block
.pow_min
-
remainder
)
/
16
;
let
repeated_zero_string
=
ZERO_STRING
.repeat
(
nb_zeros
);
if
!
hash_string
.starts_with
(
&
repeated_zero_string
)
{
return
Err
(
ZerosHashBlockError
);
}
}
// PreviousHash
// todo: solve ticket #150 (previous_hash must be an Option) before implementing this local verification
// PreviousIssuer
if
block
.number
.0
>
0
&&
block
.previous_issuer
.is_none
()
{
return
Err
(
PreviousIssuerRootBlockError
);
}
if
block
.number
.0
==
0
&&
block
.previous_issuer
.is_some
()
{
return
Err
(
PreviousIssuerRootBlockError
);
}
// Parameters
if
block
.number
.0
==
0
&&
block
.parameters
.is_none
()
{
return
Err
(
ParametersRootBlockError
);
}
if
block
.number
.0
>
0
&&
block
.parameters
.is_some
()
{
return
Err
(
ParametersRootBlockError
);
}
// Universal Dividend
if
block
.number
.0
==
0
&&
block
.dividend
.is_none
()
{
return
Err
(
UniversalDividendRootBlockError
);
}
// UnitBase
if
block
.number
.0
==
0
&&
block
.unit_base
>
0
{
return
Err
(
UnitBaseRootBlockError
);
}
// Signature
if
block
.signatures
.len
()
!=
1
{
// optimisable en ne calculant pas toute la longueur du tableau ?
return
Err
(
SignaturesLenBlockError
);
}
match
block
.verify_signatures
()
{
VerificationResult
::
Valid
()
=>
(),
_
=>
return
Err
(
SignatureBlockError
),
}
// Dates
//let avg_gen_time = block.parameters.avg_gen_time as f64;
//let maxGenTime = avg_gen_time * 1.189;
let
max_acceleration
=
1
;
// todo: max_acceleration = CEIL(maxGenTime * median_time_blocks)
if
block
.time
<
block
.median_time
||
block
.median_time
+
max_acceleration
<
block
.time
{
return
Err
(
BlockTimeError
);
}
if
block
.number
.0
==
0
&&
block
.time
!=
block
.median_time
{
return
Err
(
BlockTimeError
);
}
// Identities
for
x
in
&
block
.identities
{
match
x
.verify_signatures
()
{
VerificationResult
::
Valid
()
=>
(),
_
=>
return
Err
(
SignatureBlockError
),
}
}
// Memberships (Joiners, Actives, Leavers)
for
x
in
&
block
.joiners
{
match
x
.verify_signatures
()
{
VerificationResult
::
Valid
()
=>
(),
_
=>
return
Err
(
SignatureMembershipDocumentError
),
}
}
for
x
in
&
block
.actives
{
match
x
.verify_signatures
()
{
VerificationResult
::
Valid
()
=>
(),
_
=>
return
Err
(
SignatureMembershipDocumentError
),
}
}
for
x
in
&
block
.leavers
{
match
x
.verify_signatures
()
{
VerificationResult
::
Valid
()
=>
(),
_
=>
return
Err
(
SignatureMembershipDocumentError
),
}
}
// Revoked
for
x
in
&
block
.revoked
{
match
x
{
dubp_documents
::
text_document_traits
::
TextDocumentFormat
::
Complete
(
y
)
=>
{
match
y
.verify_signatures
()
{
VerificationResult
::
Valid
()
=>
(),
_
=>
return
Err
(
SignatureRevocationDocumentError
),
}
}
dubp_documents
::
text_document_traits
::
TextDocumentFormat
::
Compact
(
y
)
=>
{
y
match
y
.verify_signatures
()
{
VerificationResult
::
Valid
()
=>
(),
_
=>
return
Err
(
SignatureRevocationDocumentError
),
}
}
_
=>
(),
// question : ça peut arriver un compact ?
}
}
// Transactions
for
x
in
&
block
.transactions
{
match
x
{
TxDocOrTxHash
::
TxDoc
(
y
)
=>
{
// A transaction in compact format cannot measure more than 100 lines
if
y
.as_compact_text
()
.lines
()
.count
()
>=
100
{
// question : c'est strict ?
return
Err
(
TransactionDocumentError
(
LengthError
));
}
// A transaction must have at least 1 source
if
y
.get_inputs
()
.is_empty
()
{
return
Err
(
TransactionDocumentError
(
NumberSourcesError
));
}
// A transaction cannot have `SIG(INDEX)` unlocks with `INDEX >= ` issuers count. ??
if
y
.get_unlocks
()
.len
()
>=
y
.issuers
()
.len
()
{
return
Err
(
TransactionDocumentError
(
SignatureIssuerError
));
}
// A transaction's version must be equal to 3
if
y
.version
()
!=
3
{
// question : c'est certainement >= 3 vu les tests
return
Err
(
TransactionDocumentError
(
VersionError
));
}
// Signatures count must be the same as issuers count
if
y
.signatures
()
.len
()
!=
y
.issuers
()
.len
()
{
return
Err
(
TransactionDocumentError
(
SignatureCountError
));
}
/*
* A transaction **must** have signatures matching its content **for each issuer**
* Signatures are ordered by issuer
* Signatures are made over the transaction's content, signatures excepted
*/
let
result
=
y
.verify_signatures
();
match
result
{
VerificationResult
::
Valid
()
=>
(),
_
=>
return
Err
(
TransactionDocumentError
(
VerificationResult
(
result
))),
}
}
TxDocOrTxHash
::
TxHash
(
y
)
=>
{
fatal_error!
(
"Block contains a Transaction Hash (and not a Transaction Document)"
)
}
}
}
Ok
(())
}
#[cfg(test)]
mod
tests
{
#[test]
fn
generate_and_verify_block
()
{
let
mut
block
=
BlockDocument
{
nonce
:
0
,
version
:
10
,
number
:
BlockNumber
(
107_984
),
pow_min
:
88
,
time
:
1_522_685_861
,
median_time
:
1522683184
,
members_count
:
896
,
monetary_mass
:
140_469_765
,
unit_base
:
0
,
issuers_count
:
42
,
issuers_frame
:
211
,
issuers_frame_var
:
0
,
currency
:
CurrencyName
(
String
::
from
(
"g1"
)),
issuers
:
vec!
[
PubKey
::
Ed25519
(
ed25519
::
PublicKey
::
from_base58
(
"DA4PYtXdvQqk1nCaprXH52iMsK5Ahxs1nRWbWKLhpVkQ"
)
.unwrap
())],
signatures
:
vec!
[
Sig
::
Ed25519
(
ed25519
::
Signature
::
from_base64
(
"92id58VmkhgVNee4LDqBGSm8u/ooHzAD67JM6fhAE/CV8LCz7XrMF1DvRl+eRpmlaVkp6I+Iy8gmZ1WUM5C8BA=="
)
.unwrap
())],
hash
:
None
,
parameters
:
None
,
previous_hash
:
Hash
::
from_hex
(
"000001144968D0C3516BE6225E4662F182E28956AF46DD7FB228E3D0F9413FEB"
)
.expect
(
"fail to parse previous_hash"
),
previous_issuer
:
Some
(
PubKey
::
Ed25519
(
ed25519
::
PublicKey
::
from_base58
(
"D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH"
)
.unwrap
())),
inner_hash
:
None
,
dividend
:
None
,
identities
:
Vec
::
new
(),
joiners
:
Vec
::
new
(),
actives
:
Vec
::
new
(),
leavers
:
Vec
::
new
(),
revoked
:
Vec
::
new
(),
excluded
:
Vec
::
new
(),
certifications
:
vec!
[
TextDocumentFormat
::
Complete
(
cert1
)],
transactions
:
vec!
[
TxDocOrTxHash
::
TxDoc
(
Box
::
new
(
tx1
)),
TxDocOrTxHash
::
TxDoc
(
Box
::
new
(
tx2
))],
inner_hash_and_nonce_str
:
String
::
new
(),
};
assert_eq!
(
local_verification
(
&
block
),
Ok
);
}
}
pub
fn
verify_block_validity
<
W
:
WebOfTrust
>
(
block
:
&
BlockDocument
,
blockchain_db
:
&
BinDB
<
LocalBlockchainV10Datas
>
,
Loading