v3 : le vote par la chaîne Ğ1, côté moteur et serveur
Le bulletin scellé (ld1: + blake2b-256 du bulletin canonique, sel de 128 bits), l'ordre de la chaîne (bloc, puis rang de l'événement : le dernier fait foi), les adresses SS58 comparées par clé (ld-engine, pur). trustin-access : Monnaie libre vote par la chaîne, les groupes gérés sur le serveur ; le droit de vote se lit à la confirmation. Serveur : bulletins en attente, confirmation sur l'indexeur (virement, auteur, identité, membre), identité idty:<index> créée au besoin, tâche de fond toutes les 10 s, expiration à 24 h, vote groupé en une écriture dans les groupes gérés. Migration additive 0006. Sans LD_VOTE_ACCOUNT, le vote par la chaîne est éteint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,39 @@ pub struct Publish {
|
||||
pub author_email: String,
|
||||
}
|
||||
|
||||
/// The vote on the Ğ1 chain (ADR 0008): where the 0.1 Ğ1 of each vote go, how
|
||||
/// much, and the nodes the page sends the transaction to. Without
|
||||
/// `LD_VOTE_ACCOUNT`, voting through the chain is off, and the interface says so.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VoteChain {
|
||||
/// The vote account, as a Ğ1 address (`g1…`), whatever form it was given in.
|
||||
pub account: String,
|
||||
pub account_key: [u8; 32],
|
||||
/// Cents of Ğ1 per vote (`LD_VOTE_AMOUNT`, 10 = 0.1 Ğ1 by default).
|
||||
pub amount: u64,
|
||||
/// WebSocket endpoints of Ğ1 nodes, for the page (`LD_VOTE_NODES`).
|
||||
pub nodes: Vec<String>,
|
||||
/// Tests only, with the dev login: the page sends to this fake node instead
|
||||
/// of building the transaction with polkadot-api (`LD_VOTE_TEST_NODE`).
|
||||
pub test_node: Option<String>,
|
||||
}
|
||||
|
||||
impl VoteChain {
|
||||
pub const DEFAULT_AMOUNT: u64 = 10;
|
||||
|
||||
/// From the account in any SS58 form; `None` if it is not an address.
|
||||
pub fn new(account: &str, amount: u64, nodes: Vec<String>, test_node: Option<String>) -> Option<Self> {
|
||||
let (_, key) = ld_engine::address::decode(account.trim())?;
|
||||
Some(Self {
|
||||
account: ld_engine::address::encode(ld_engine::address::G1_PREFIX, &key),
|
||||
account_key: key,
|
||||
amount: amount.max(1),
|
||||
nodes,
|
||||
test_node,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Config {
|
||||
pub bind: String,
|
||||
@@ -38,6 +71,8 @@ pub struct Config {
|
||||
pub indexers: Vec<String>,
|
||||
pub wot_fallback: u32,
|
||||
pub build: String,
|
||||
/// The vote on the chain; `None` = off (no `LD_VOTE_ACCOUNT`).
|
||||
pub vote: Option<VoteChain>,
|
||||
}
|
||||
|
||||
fn var(name: &str) -> Option<String> {
|
||||
@@ -76,6 +111,18 @@ impl Config {
|
||||
author_name: var("LD_PUBLISH_AUTHOR").unwrap_or_else(|| "libreDecision".into()),
|
||||
author_email: var("LD_PUBLISH_EMAIL").unwrap_or_else(|| "decision@librodrome.org".into()),
|
||||
});
|
||||
let dev_login = flag("LD_DEV_LOGIN");
|
||||
let vote = var("LD_VOTE_ACCOUNT").and_then(|account| {
|
||||
let amount = var("LD_VOTE_AMOUNT").and_then(|v| v.parse().ok()).unwrap_or(VoteChain::DEFAULT_AMOUNT);
|
||||
let nodes = list("LD_VOTE_NODES", &["wss://rpc.duniter.org", "wss://g1.axiom-team.fr/ws"]);
|
||||
// A fake node for the page, never outside the local dev login.
|
||||
let test_node = var("LD_VOTE_TEST_NODE").filter(|_| dev_login);
|
||||
let chain = VoteChain::new(&account, amount, nodes, test_node);
|
||||
if chain.is_none() {
|
||||
tracing::error!("LD_VOTE_ACCOUNT is not a Ğ1 address: the vote through the chain stays off");
|
||||
}
|
||||
chain
|
||||
});
|
||||
Self {
|
||||
bind: var("LD_BIND").unwrap_or_else(|| "0.0.0.0:8002".into()),
|
||||
web_dir: PathBuf::from(var("LD_WEB_DIR").unwrap_or_else(|| "web/build".into())),
|
||||
@@ -86,7 +133,7 @@ impl Config {
|
||||
.to_owned(),
|
||||
connect,
|
||||
admin_g1_ids: list("LD_ADMIN_G1_IDS", &[]),
|
||||
dev_login: flag("LD_DEV_LOGIN"),
|
||||
dev_login,
|
||||
bootstrap_admin: flag("LD_BOOTSTRAP_ADMIN"),
|
||||
publish,
|
||||
rpc_endpoints: list(
|
||||
@@ -104,6 +151,7 @@ impl Config {
|
||||
),
|
||||
wot_fallback: var("LD_WOT_FALLBACK").and_then(|v| v.parse().ok()).unwrap_or(5745),
|
||||
build: var("LD_BUILD").unwrap_or_else(|| "dev".into()),
|
||||
vote,
|
||||
data_dir,
|
||||
}
|
||||
}
|
||||
@@ -134,6 +182,7 @@ impl Config {
|
||||
indexers: vec![],
|
||||
wot_fallback: 5745,
|
||||
build: "test".into(),
|
||||
vote: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user