Browse Source

darkfid: Implement RPC endpoint for building a merkle path from leaf position.

parazyd 4 years ago
parent
commit
e758949d92
4 changed files with 28 additions and 0 deletions
  1. 1 0
      Cargo.lock
  2. 1 0
      bin/darkfid/Cargo.toml
  3. 1 0
      bin/darkfid/src/main.rs
  4. 25 0
      bin/darkfid/src/rpc_wallet.rs

+ 1 - 0
Cargo.lock

@@ -1271,6 +1271,7 @@ dependencies = [
  "easy-parallel",
  "easy-parallel",
  "futures-lite",
  "futures-lite",
  "fxhash",
  "fxhash",
+ "incrementalmerkletree",
  "lazy-init",
  "lazy-init",
  "log",
  "log",
  "num-bigint",
  "num-bigint",

+ 1 - 0
bin/darkfid/Cargo.toml

@@ -21,6 +21,7 @@ darkfi = {path = "../../", features = ["blockchain", "wallet", "rpc", "net", "no
 easy-parallel = "3.2.0"
 easy-parallel = "3.2.0"
 futures-lite = "1.12.0"
 futures-lite = "1.12.0"
 fxhash = "0.2.1"
 fxhash = "0.2.1"
+incrementalmerkletree = "0.3.0"
 lazy-init = "0.5.1"
 lazy-init = "0.5.1"
 log = "0.4.17"
 log = "0.4.17"
 num-bigint = {version = "0.4.3", features = ["serde"]}
 num-bigint = {version = "0.4.3", features = ["serde"]}

+ 1 - 0
bin/darkfid/src/main.rs

@@ -184,6 +184,7 @@ impl RequestHandler for Darkfid {
             }
             }
             Some("wallet.get_balances") => return self.get_balances(req.id, params).await,
             Some("wallet.get_balances") => return self.get_balances(req.id, params).await,
             Some("wallet.get_coins_valtok") => return self.get_coins_valtok(req.id, params).await,
             Some("wallet.get_coins_valtok") => return self.get_coins_valtok(req.id, params).await,
+            Some("wallet.get_merkle_path") => return self.get_merkle_path(req.id, params).await,
             Some(_) | None => return JsonError::new(MethodNotFound, None, req.id).into(),
             Some(_) | None => return JsonError::new(MethodNotFound, None, req.id).into(),
         }
         }
     }
     }

+ 25 - 0
bin/darkfid/src/rpc_wallet.rs

@@ -1,4 +1,5 @@
 use fxhash::FxHashMap;
 use fxhash::FxHashMap;
+use incrementalmerkletree::Tree;
 use log::error;
 use log::error;
 use pasta_curves::group::ff::PrimeField;
 use pasta_curves::group::ff::PrimeField;
 use serde_json::{json, Value};
 use serde_json::{json, Value};
@@ -258,4 +259,28 @@ impl Darkfid {
             coins.iter().map(|x| bs58::encode(serialize(x)).into_string()).collect();
             coins.iter().map(|x| bs58::encode(serialize(x)).into_string()).collect();
         JsonResponse::new(json!(ret), id).into()
         JsonResponse::new(json!(ret), id).into()
     }
     }
+
+    // RPCAPI:
+    // Query the state merkle tree for the merkle path of a given leaf position.
+    // --> {"jsonrpc": "2.0", "method": "wallet.get_merkle_path", "params": [3], "id": 1}
+    // <-- {"jsonrpc": "2.0", "result": ["f091uf1...", "081ff0h10w1h0...", ...], "id": 1}
+    pub async fn get_merkle_path(&self, id: Value, params: &[Value]) -> JsonResult {
+        if params.len() != 1 || !params[0].is_u64() {
+            return JsonError::new(InvalidParams, None, id).into()
+        }
+
+        let leaf_pos: incrementalmerkletree::Position =
+            ((params[0].as_u64().unwrap() as u64) as usize).into();
+
+        let validator_state = self.validator_state.read().await;
+        let state = validator_state.state_machine.lock().await;
+        let root = state.tree.root(0).unwrap();
+        let merkle_path = state.tree.authentication_path(leaf_pos, &root).unwrap();
+        drop(state);
+        drop(validator_state);
+
+        let ret: Vec<String> =
+            merkle_path.iter().map(|x| bs58::encode(serialize(x)).into_string()).collect();
+        JsonResponse::new(json!(ret), id).into()
+    }
 }
 }