Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Duniter v2S
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
Monitor
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
nodes
rust
Duniter v2S
Commits
60b5a7d6
Commit
60b5a7d6
authored
1 year ago
by
Cédric Moreau
Browse files
Options
Downloads
Patches
Plain Diff
fix(
#125
): GenesisConfig must be derived from GenesisData (GDev)
parent
10eee6cc
No related branches found
No related tags found
No related merge requests found
Pipeline
#33318
failed
1 year ago
Stage: labels
Stage: quality
Stage: build
Stage: tests
Stage: deploy
Changes
2
Pipelines
2
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
node/src/chain_spec/gdev.rs
+122
-523
122 additions, 523 deletions
node/src/chain_spec/gdev.rs
node/src/chain_spec/gen_genesis_data.rs
+223
-36
223 additions, 36 deletions
node/src/chain_spec/gen_genesis_data.rs
with
345 additions
and
559 deletions
node/src/chain_spec/gdev.rs
+
122
−
523
View file @
60b5a7d6
This diff is collapsed.
Click to expand it.
node/src/chain_spec/gen_genesis_data.rs
+
223
−
36
View file @
60b5a7d6
...
@@ -14,13 +14,14 @@
...
@@ -14,13 +14,14 @@
// You should have received a copy of the GNU Affero General Public License
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
use
crate
::
chain_spec
::
gdev
::{
get_authority_keys_from_seed
,
get_env
,
session_keys
,
AuthorityKeys
};
use
crate
::
chain_spec
::{
clique_wot
,
get_account_id_from_seed
,
NAMES
};
use
common_runtime
::
*
;
use
common_runtime
::
*
;
use
maplit
::
btreemap
;
use
maplit
::
btreemap
;
use
serde
::{
de
::
DeserializeOwned
,
Deserialize
,
Serialize
};
use
serde
::{
de
::
DeserializeOwned
,
Deserialize
,
Serialize
};
use
sp_core
::
crypto
::
AccountId32
;
use
sp_core
::
crypto
::
AccountId32
;
use
sp_core
::{
blake2_256
,
Decode
,
Encode
,
H256
};
use
sp_core
::{
blake2_256
,
sr25519
,
Decode
,
Encode
,
H256
};
use
std
::
collections
::
BTreeMap
;
use
std
::
collections
::
BTreeMap
;
use
std
::
fmt
::
format
;
type
MembershipData
=
sp_membership
::
MembershipData
<
u32
>
;
type
MembershipData
=
sp_membership
::
MembershipData
<
u32
>
;
...
@@ -61,7 +62,7 @@ struct GenesisConfig<Parameters> {
...
@@ -61,7 +62,7 @@ struct GenesisConfig<Parameters> {
#[serde(default)]
#[serde(default)]
parameters
:
Parameters
,
parameters
:
Parameters
,
#[serde(rename
=
"smiths"
)]
#[serde(rename
=
"smiths"
)]
smith_identities
:
BTreeMap
<
String
,
SmithData
>
,
smith_identities
:
Vec
<
SmithData
>
,
sudo_key
:
Option
<
AccountId
>
,
sudo_key
:
Option
<
AccountId
>
,
technical_committee
:
Vec
<
String
>
,
technical_committee
:
Vec
<
String
>
,
ud
:
u64
,
ud
:
u64
,
...
@@ -87,9 +88,8 @@ struct Idty {
...
@@ -87,9 +88,8 @@ struct Idty {
#[derive(Clone,
Deserialize,
Serialize)]
#[derive(Clone,
Deserialize,
Serialize)]
struct
SmithData
{
struct
SmithData
{
name
:
String
,
session_keys
:
Option
<
String
>
,
session_keys
:
Option
<
String
>
,
#[serde(default)]
certs
:
Vec
<
Cert
>
,
}
}
#[derive(Clone,
Deserialize,
Serialize)]
#[derive(Clone,
Deserialize,
Serialize)]
...
@@ -111,8 +111,9 @@ impl From<Cert> for (String, Option<u32>) {
...
@@ -111,8 +111,9 @@ impl From<Cert> for (String, Option<u32>) {
/// takes DUNITER_GENESIS_CONFIG env var if present or duniter-gen-conf.json by default
/// takes DUNITER_GENESIS_CONFIG env var if present or duniter-gen-conf.json by default
// this function is targeting dev chainspecs, do not use in production network
// this function is targeting dev chainspecs, do not use in production network
pub
fn
generate_genesis_data
<
CS
,
P
,
SK
,
F
>
(
pub
fn
generate_genesis_data
<
CS
,
P
,
SK
,
F
>
(
json_file_path
:
String
,
f
:
F
,
f
:
F
,
maybe_force_authority
:
Option
<
Vec
<
u8
>>
,
maybe_force_authority
:
Option
<
(
String
,
Vec
<
u8
>
)
>
,
)
->
Result
<
CS
,
String
>
)
->
Result
<
CS
,
String
>
where
where
P
:
Default
+
DeserializeOwned
,
P
:
Default
+
DeserializeOwned
,
...
@@ -138,7 +139,9 @@ where
...
@@ -138,7 +139,9 @@ where
technical_committee
,
technical_committee
,
ud
,
ud
,
// wallets,
// wallets,
}
=
get_genesis_config
::
<
P
>
()
?
;
}
=
get_genesis_config
::
<
P
>
(
std
::
env
::
var
(
"DUNITER_GENESIS_CONFIG"
)
.unwrap_or_else
(|
_
|
json_file_path
.to_owned
()),
)
?
;
let
GenesisMigrationData
{
let
GenesisMigrationData
{
identities
,
identities
,
...
@@ -247,16 +250,16 @@ where
...
@@ -247,16 +250,16 @@ where
}
}
// Verify certifications coherence
// Verify certifications coherence
let
mut
not_enough_certs
:
Vec
<
u32
>
=
vec!
[];
for
(
idty_index
,
receiver_certs
)
in
&
certs_by_receiver
{
for
(
idty_index
,
receiver_certs
)
in
&
certs_by_receiver
{
if
receiver_certs
.len
()
<
genesis_certs_min_received
as
usize
{
if
receiver_certs
.len
()
<
genesis_certs_min_received
as
usize
{
return
Err
(
format!
(
not_enough_certs
.push
(
*
idty_index
);
"Identity n°{} has received only {}/{} certifications)"
,
idty_index
,
receiver_certs
.len
(),
genesis_certs_min_received
));
}
}
}
}
// Trim these identities
not_enough_certs
.into_iter
()
.for_each
(|
idty_index
|
{
certs_by_receiver
.remove
(
&
idty_index
);
});
// SMITHS SUB-WOT //
// SMITHS SUB-WOT //
...
@@ -265,13 +268,25 @@ where
...
@@ -265,13 +268,25 @@ where
let
mut
session_keys_map
=
BTreeMap
::
new
();
let
mut
session_keys_map
=
BTreeMap
::
new
();
let
mut
smith_memberships
=
BTreeMap
::
new
();
let
mut
smith_memberships
=
BTreeMap
::
new
();
let
mut
smith_certs_by_receiver
=
BTreeMap
::
new
();
let
mut
smith_certs_by_receiver
=
BTreeMap
::
new
();
for
(
idty_name
,
smith_data
)
in
smith_identities
{
// Authorities
let
authority_idty_index
=
maybe_force_authority
.clone
()
.map
(|(
name
,
_
)|
{
idty_index_of
.get
(
&
name
)
.ok_or
(
format!
(
"Identity '{}' not exist"
,
name
))
.expect
(
"Initial authority must have an identity"
)
});
for
SmithData
{
name
:
idty_name
,
session_keys
,
}
in
&
smith_identities
{
let
idty_index
=
idty_index_of
let
idty_index
=
idty_index_of
.get
(
&
idty_name
)
.get
(
idty_name
)
.ok_or
(
format!
(
"Identity '{}' not exist"
,
&
idty_name
))
?
;
.ok_or
(
format!
(
"Identity '{}' not exist"
,
idty_name
))
?
;
let
identity
=
identities
let
identity
=
identities
.get
(
&
idty_name
)
.get
(
idty_name
)
.ok_or
(
format!
(
"Identity '{}' not exist"
,
&
idty_name
))
?
;
.ok_or
(
format!
(
"Identity '{}' not exist"
,
idty_name
))
?
;
if
identity
.balance
<
EXISTENTIAL_DEPOSIT
{
if
identity
.balance
<
EXISTENTIAL_DEPOSIT
{
return
Err
(
format!
(
return
Err
(
format!
(
...
@@ -281,11 +296,11 @@ where
...
@@ -281,11 +296,11 @@ where
}
}
// Initial authorities
// Initial authorities
if
maybe_force_authority
.is_some
()
{
if
let
Some
(
authority_idty_index
)
=
authority_idty_index
{
if
smith_data
.
session_keys
.is_some
()
{
if
session_keys
.is_some
()
{
return
Err
(
"session_keys field forbidden"
.to_owned
());
return
Err
(
"session_keys field forbidden"
.to_owned
());
}
}
if
*
idty_index
==
1
{
if
*
idty_index
==
*
authority_idty_index
{
// online authority
// online authority
initial_authorities
.insert
(
1
,
(
identity
.pubkey
.clone
(),
true
));
initial_authorities
.insert
(
1
,
(
identity
.pubkey
.clone
(),
true
));
}
else
{
}
else
{
...
@@ -295,16 +310,17 @@ where
...
@@ -295,16 +310,17 @@ where
}
else
{
}
else
{
initial_authorities
.insert
(
initial_authorities
.insert
(
*
idty_index
,
*
idty_index
,
(
identity
.pubkey
.clone
(),
smith_data
.
session_keys
.is_some
()),
(
identity
.pubkey
.clone
(),
session_keys
.is_some
()),
);
);
}
}
// Session keys
// Session keys
let
session_keys_bytes
=
if
let
Some
(
ref
session_keys
)
=
smith_data
.
session_keys
{
let
session_keys_bytes
=
if
let
Some
(
ref
session_keys
)
=
session_keys
{
online_authorities_counter
+=
1
;
online_authorities_counter
+=
1
;
hex
::
decode
(
&
session_keys
[
2
..
])
hex
::
decode
(
&
session_keys
[
2
..
])
.map_err
(|
_
|
format!
(
"invalid session keys for idty {}"
,
&
idty_name
))
?
.map_err
(|
_
|
format!
(
"invalid session keys for idty {}"
,
idty_name
))
?
}
else
if
let
(
1
,
Some
(
ref
session_keys_bytes
))
=
(
*
idty_index
,
&
maybe_force_authority
)
{
}
else
if
let
(
1
,
Some
((
_
,
ref
session_keys_bytes
)))
=
(
*
idty_index
,
&
maybe_force_authority
)
{
session_keys_bytes
.clone
()
session_keys_bytes
.clone
()
}
else
{
}
else
{
// Create fake session keys (must be unique and deterministic)
// Create fake session keys (must be unique and deterministic)
...
@@ -316,18 +332,22 @@ where
...
@@ -316,18 +332,22 @@ where
//vec![initial_authorities.len() as u8; std::mem::size_of::<SK>()]
//vec![initial_authorities.len() as u8; std::mem::size_of::<SK>()]
};
};
let
session_keys
=
SK
::
decode
(
&
mut
&
session_keys_bytes
[
..
])
let
session_keys
=
SK
::
decode
(
&
mut
&
session_keys_bytes
[
..
])
.map_err
(|
_
|
format!
(
"invalid session keys for idty {}"
,
&
idty_name
))
?
;
.map_err
(|
_
|
format!
(
"invalid session keys for idty {}"
,
idty_name
))
?
;
session_keys_map
.insert
(
identity
.pubkey
.clone
(),
session_keys
);
session_keys_map
.insert
(
identity
.pubkey
.clone
(),
session_keys
);
// Certifications
// Certifications
let
mut
receiver_certs
=
BTreeMap
::
new
();
let
mut
receiver_certs
=
BTreeMap
::
new
();
for
cert
in
&
smith_data
.certs
{
// All initial smiths are considered to be certifying all each other
let
(
issuer
,
maybe_expire_on
)
=
cert
.clone
()
.into
();
smith_identities
let
issuer_index
=
idty_index_of
.iter
()
.get
(
&
issuer
)
.filter
(|
s
|
s
.name
.to_owned
()
!=
*
idty_name
)
.ok_or
(
format!
(
"Identity '{}' not exist"
,
issuer
))
?
;
.for_each
(|
other_smith
|
{
receiver_certs
.insert
(
*
issuer_index
,
maybe_expire_on
);
let
issuer_index
=
idty_index_of
}
.get
(
&
other_smith
.name
)
.ok_or
(
format!
(
"Identity '{}' not exist"
,
other_smith
.name
))
.unwrap
();
receiver_certs
.insert
(
*
issuer_index
,
None
);
// TODO: put duration
});
smith_certs_by_receiver
.insert
(
*
idty_index
,
receiver_certs
);
smith_certs_by_receiver
.insert
(
*
idty_index
,
receiver_certs
);
// Memberships
// Memberships
...
@@ -382,6 +402,173 @@ where
...
@@ -382,6 +402,173 @@ where
Ok
(
f
(
genesis_data
))
Ok
(
f
(
genesis_data
))
}
}
pub
fn
generate_genesis_data_for_benchmark_chain
<
CS
,
P
,
SK
,
F
>
(
initial_authorities_len
:
usize
,
initial_smiths_len
:
usize
,
initial_identities_len
:
usize
,
root_key
:
AccountId
,
_enable_println
:
bool
,
f
:
F
,
)
->
Result
<
CS
,
String
>
where
P
:
Default
+
DeserializeOwned
,
SK
:
Decode
,
F
:
Fn
(
GenesisData
<
P
,
SK
>
)
->
CS
,
{
// Same as local chain
generate_genesis_data_for_local_chain
(
initial_authorities_len
,
initial_smiths_len
,
initial_identities_len
,
root_key
,
_enable_println
,
f
,
)
}
pub
fn
generate_genesis_data_for_local_chain
<
CS
,
P
,
SK
,
F
>
(
initial_authorities_len
:
usize
,
initial_smiths_len
:
usize
,
initial_identities_len
:
usize
,
root_key
:
AccountId
,
_enable_println
:
bool
,
f
:
F
,
)
->
Result
<
CS
,
String
>
where
P
:
Default
+
DeserializeOwned
,
SK
:
Decode
,
F
:
Fn
(
GenesisData
<
P
,
SK
>
)
->
CS
,
{
assert!
(
initial_identities_len
<=
6
);
assert!
(
initial_smiths_len
<=
initial_identities_len
);
assert!
(
initial_authorities_len
<=
initial_smiths_len
);
let
babe_epoch_duration
=
get_env
(
"DUNITER_BABE_EPOCH_DURATION"
,
30
)
as
u64
;
let
cert_validity_period
=
get_env
(
"DUNITER_CERT_VALIDITY_PERIOD"
,
1_000
);
let
membership_period
=
get_env
(
"DUNITER_MEMBERSHIP_PERIOD"
,
1_000
);
let
smith_cert_validity_period
=
get_env
(
"DUNITER_SMITH_CERT_VALIDITY_PERIOD"
,
1_000
);
let
smith_membership_period
=
get_env
(
"DUNITER_SMITH_MEMBERSHIP_PERIOD"
,
1_000
);
let
ud_creation_period
=
get_env
(
"DUNITER_UD_CREATION_PERIOD"
,
60_000
);
let
ud_reeval_period
=
get_env
(
"DUNITER_UD_REEEVAL_PERIOD"
,
1_200_000
);
let
ud
=
1_000
;
let
initial_smiths
=
(
0
..
initial_smiths_len
)
.map
(|
i
|
get_authority_keys_from_seed
(
NAMES
[
i
]))
.collect
::
<
Vec
<
AuthorityKeys
>>
();
let
initial_identities
=
(
0
..
initial_identities_len
)
.map
(|
i
|
{
(
IdtyName
::
from
(
NAMES
[
i
]),
get_account_id_from_seed
::
<
sr25519
::
Public
>
(
NAMES
[
i
]),
)
})
.collect
::
<
BTreeMap
<
IdtyName
,
AccountId
>>
();
let
mut
session_keys_map
=
BTreeMap
::
new
();
initial_smiths
.iter
()
.for_each
(|
x
|
{
let
session_keys_bytes
=
session_keys
(
x
.1
.clone
(),
x
.2
.clone
(),
x
.3
.clone
(),
x
.4
.clone
())
.encode
();
let
sk
=
SK
::
decode
(
&
mut
&
session_keys_bytes
[
..
])
.map_err
(|
_
|
format!
(
"invalid session keys for idty {}"
,
x
.0
.clone
()))
.unwrap
();
session_keys_map
.insert
(
x
.0
.clone
(),
sk
);
});
let
identities_
=
initial_identities
.iter
()
.enumerate
()
.map
(|(
_
,
(
name
,
owner_key
))|
{
(
String
::
from_utf8
(
name
.0
.clone
())
.unwrap
(),
owner_key
.clone
(),
)
})
.collect
();
let
parameters
=
serde_json
::
from_slice
::
<
P
>
(
format!
(
"{{
\"
babe_epoch_duration
\"
: {},
\"
cert_period
\"
: 15,
\"
cert_max_by_issuer
\"
: 10,
\"
cert_min_received_cert_to_issue_cert
\"
: 2,
\"
cert_validity_period
\"
: {},
\"
idty_confirm_period
\"
: 40,
\"
idty_creation_period
\"
: 50,
\"
membership_period
\"
: {},
\"
pending_membership_period
\"
: 500,
\"
ud_creation_period
\"
: {},
\"
ud_reeval_period
\"
: {},
\"
smith_cert_period
\"
: 15,
\"
smith_cert_max_by_issuer
\"
: 8,
\"
smith_cert_min_received_cert_to_issue_cert
\"
: 2,
\"
smith_cert_validity_period
\"
: {},
\"
smith_membership_period
\"
: {},
\"
smith_pending_membership_period
\"
: 500,
\"
smith_wot_first_cert_issuable_on
\"
: 20,
\"
smith_wot_min_cert_for_membership
\"
: 2,
\"
wot_first_cert_issuable_on
\"
: 20,
\"
wot_min_cert_for_create_idty_right
\"
: 2,
\"
wot_min_cert_for_membership
\"
: 2
}}"
,
babe_epoch_duration
,
cert_validity_period
,
membership_period
,
ud_creation_period
,
ud_reeval_period
,
smith_cert_validity_period
,
smith_membership_period
)
.as_bytes
(),
)
.map_err
(|
e
|
format!
(
"Error parsing json conf: {}"
,
e
))
?
;
let
genesis_data
=
GenesisData
{
accounts
:
initial_identities
.iter
()
.enumerate
()
.map
(|(
i
,
(
_
,
owner_key
))|
{
(
owner_key
.clone
(),
GenesisAccountData
{
random_id
:
H256
(
blake2_256
(
&
(
i
as
u32
,
owner_key
)
.encode
())),
balance
:
ud
,
is_identity
:
true
,
},
)
})
.collect
(),
certs_by_receiver
:
clique_wot
(
initial_identities
.len
()),
first_ud
:
None
,
first_ud_reeval
:
None
,
identities
:
identities_
,
initial_authorities
:
initial_smiths
.iter
()
.enumerate
()
.map
(|(
i
,
keys
)|
(
i
as
u32
+
1
,
(
keys
.0
.clone
(),
i
<
initial_authorities_len
)))
.collect
(),
initial_monetary_mass
:
initial_identities_len
as
u64
*
ud
,
memberships
:
(
1
..=
initial_identities
.len
())
.map
(|
i
|
(
i
as
u32
,
MembershipData
{
expire_on
:
0
}))
.collect
(),
// TODO: remove this P generic parameter thats makes this ugly parsing mandatory
parameters
,
session_keys_map
,
smith_certs_by_receiver
:
clique_wot
(
initial_smiths_len
),
smith_memberships
:
(
1
..=
initial_smiths_len
)
.map
(|
i
|
(
i
as
u32
,
MembershipData
{
expire_on
:
0
}))
.collect
(),
sudo_key
:
Some
(
root_key
),
technical_committee_members
:
initial_smiths
.iter
()
.map
(|
x
|
x
.0
.clone
())
.collect
::
<
Vec
<
_
>>
(),
ud
,
};
Ok
(
f
(
genesis_data
))
}
fn
check_parameters_consistency
(
fn
check_parameters_consistency
(
wallets
:
&
BTreeMap
<
AccountId32
,
u64
>
,
wallets
:
&
BTreeMap
<
AccountId32
,
u64
>
,
first_ud
:
&
Option
<
u64
>
,
first_ud
:
&
Option
<
u64
>
,
...
@@ -415,9 +602,9 @@ fn check_parameters_consistency(
...
@@ -415,9 +602,9 @@ fn check_parameters_consistency(
Ok
(())
Ok
(())
}
}
fn
get_genesis_config
<
P
:
Default
+
DeserializeOwned
>
(
)
->
Result
<
GenesisConfig
<
P
>
,
String
>
{
fn
get_genesis_config
<
P
:
Default
+
DeserializeOwned
>
(
let
json_file_path
=
std
::
env
::
var
(
"DUNITER_GENESIS_CONFIG"
)
json_file_path
:
String
,
.unwrap_or_else
(|
_
|
"duniter-gen-conf.json"
.to_owned
());
)
->
Result
<
GenesisConfig
<
P
>
,
String
>
{
// We mmap the file into memory first, as this is *a lot* faster than using
// We mmap the file into memory first, as this is *a lot* faster than using
// `serde_json::from_reader`. See https://github.com/serde-rs/json/issues/160
// `serde_json::from_reader`. See https://github.com/serde-rs/json/issues/160
let
file
=
std
::
fs
::
File
::
open
(
&
json_file_path
)
let
file
=
std
::
fs
::
File
::
open
(
&
json_file_path
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment