Fill in some TODOs

This commit is contained in:
Thomas Eizinger 2021-05-04 17:58:54 +10:00
parent 21f31ccb8d
commit be9c2c7d6b
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96
7 changed files with 98 additions and 131 deletions

1
Cargo.lock generated
View File

@ -2350,6 +2350,7 @@ name = "monero-wallet"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait",
"curve25519-dalek", "curve25519-dalek",
"monero", "monero",
"monero-harness", "monero-harness",

View File

@ -5,11 +5,15 @@ use curve25519_dalek::edwards::EdwardsPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use hash_edwards_to_edwards::hash_point_to_point; use hash_edwards_to_edwards::hash_point_to_point;
use itertools::Itertools; use itertools::Itertools;
use monero::blockdata::transaction::{ExtraField, SubField, TxOutTarget};
use monero::cryptonote::hash::Hashable; use monero::cryptonote::hash::Hashable;
use monero::util::ringct::{RctSig, RctSigBase, RctSigPrunable, RctType}; use monero::cryptonote::onetime_key::KeyGenerator;
use monero::{Transaction, TransactionPrefix, TxIn, VarInt}; use monero::util::ringct::{EcdhInfo, RctSig, RctSigBase, RctSigPrunable, RctType};
use monero::{PrivateKey, PublicKey};
use monero::{Transaction, TransactionPrefix, TxIn, TxOut, VarInt};
use monero_rpc::monerod; use monero_rpc::monerod;
use monero_rpc::monerod::{GetOutputsOut, MonerodRpc}; use monero_rpc::monerod::{GetOutputsOut, MonerodRpc};
use monero_wallet::{MonerodClientExt, Wallet};
use rand::rngs::OsRng; use rand::rngs::OsRng;
use rand::{Rng, SeedableRng}; use rand::{Rng, SeedableRng};
use std::convert::TryInto; use std::convert::TryInto;
@ -18,6 +22,13 @@ use std::iter;
// [0u8; 32] = 466iKkx7MqVGD46dje3kwvSQRMfhNCvGaXTRATbQgz7kS8XTMmRmoTw9oJRRj523kTdQj8gXnF2xU9fmEPy9WXTr6pwetQj // [0u8; 32] = 466iKkx7MqVGD46dje3kwvSQRMfhNCvGaXTRATbQgz7kS8XTMmRmoTw9oJRRj523kTdQj8gXnF2xU9fmEPy9WXTr6pwetQj
// [1u8; 32] = 47HCnKkBEeYfX5pScvBETAKdjBEPN7FcXEJPUqDPzWGCc6wC8VAdS8CjdtgKuSaY72K8fkoswjp176vbSPS8hzS17EZv8gj // [1u8; 32] = 47HCnKkBEeYfX5pScvBETAKdjBEPN7FcXEJPUqDPzWGCc6wC8VAdS8CjdtgKuSaY72K8fkoswjp176vbSPS8hzS17EZv8gj
#[tokio::test]
async fn make_blocks() {
let client = monerod::Client::localhost(18081).unwrap();
client.generateblocks(10, "47HCnKkBEeYfX5pScvBETAKdjBEPN7FcXEJPUqDPzWGCc6wC8VAdS8CjdtgKuSaY72K8fkoswjp176vbSPS8hzS17EZv8gj".to_owned()).await.unwrap();
}
#[tokio::test] #[tokio::test]
async fn monerod_integration_test() { async fn monerod_integration_test() {
let client = monerod::Client::localhost(18081).unwrap(); let client = monerod::Client::localhost(18081).unwrap();
@ -32,9 +43,7 @@ async fn monerod_integration_test() {
let lock_address = monero::Address::from_keypair(monero::Network::Mainnet, &lock_kp); let lock_address = monero::Address::from_keypair(monero::Network::Mainnet, &lock_kp);
dbg!(lock_address); let spend_tx = "c9b8c57097fe3af0bffcc7470355afa804be2cad0c559a99506ac040cb93d62d"
let spend_tx = "d5d82405a655ebf721e32c8ef2f8b77f2476dd7cbdb06c05b9735abdf9a2a927"
.parse() .parse()
.unwrap(); .unwrap();
@ -42,8 +51,7 @@ async fn monerod_integration_test() {
let real_key_offset = o_indexes_response.o_indexes.pop().unwrap(); let real_key_offset = o_indexes_response.o_indexes.pop().unwrap();
// let (lower, upper) = dbg!(wallet.calculate_key_offset_boundaries().await.unwrap()); let (lower, upper) = client.calculate_key_offset_boundaries().await.unwrap();
let (lower, upper) = (VarInt(77), VarInt(117));
let mut key_offsets = Vec::with_capacity(11); let mut key_offsets = Vec::with_capacity(11);
key_offsets.push(VarInt(real_key_offset)); key_offsets.push(VarInt(real_key_offset));
@ -83,93 +91,14 @@ async fn monerod_integration_test() {
key_offsets.sort(); key_offsets.sort();
// [
// OutKey {
// height: 80,
// key: 90160faa3f57077ee05eaae797d95eae96d6d6b31f02df274ded85a63b5f2987,
// mask: be8aa4ab10aab1cd1920b83243ebdfb84c2275dc0eaeee8b7e202c3d1f314c92,
// txid: 0x1062a5b667023ebbb39fbc8898ea43488f83fbf877c790895c3882d4f1ef65cd,
// unlocked: false,
// },
// OutKey {
// height: 85,
// key: 97d00aca5023c8092b1070442169b1088f533904e2938ad52696324ee1fbb780,
// mask: 1b68a61d530c63749269ee5b4b4ff251944489aa636e92b78dac78a5b0f964c7,
// txid: 0x505d33dd8e5e891e5e10010a8188d3f9303d1939b3801a3385e6acd15b81ab57,
// unlocked: false,
// },
// OutKey {
// height: 89,
// key: 3645d682a5a13e4f58fb3d711f247237251ba8f38d2bf6f00dc974db14e1ceac,
// mask: 2e3e47603f364de65dfce86090f9943a0f702f53cdd2fc03ab537c899a5eae67,
// txid: 0x96e730e7aebfbf9863f18541c12ab49fb6b9dd44eff85369b0b70f85a4afc37b,
// unlocked: false,
// },
// OutKey {
// height: 90,
// key: 5e0f69d43987c49d5ded18aa20ea81df9aa133a30e917ec7549e2f29978674ec,
// mask: d9f4bf0287eefb653575b1c7ed3a377f45c29318fbb5f91989ffa9c986acbeff,
// txid: 0x4855aa4b17e847b928fb452a762302962b80905ea83708f83a87d18884dc3adc,
// unlocked: false,
// },
// OutKey {
// height: 91,
// key: f3d362c830e20a365e6f2f13e05d21dabcb6ac9517351dcaa66da64d38af8a28,
// mask: c8e768cbf939f780f6197b8c0d7a1baa3caf0407fdee3f555fd791a740e85e6a,
// txid: 0x495d961a96db30d0bcbc89acda693ceb371ecf56b4b036f8c0511b5bf5688579,
// unlocked: false,
// },
// OutKey {
// height: 96,
// key: 1f51a5f61d7d8e2ae431488c62e4e6523c02856a03af7d0c51929fa9c94da0b8,
// mask: 167200b570a7b31bf23b3f8c111b03d073f128895a33a9de8ed2b8b839b42ff9,
// txid: 0xdb7ee874506e2f75d52e2ae7f4d140dbd37cceba870aef2ffe25a417094991d4,
// unlocked: false,
// },
// OutKey {
// height: 105,
// key: c34378e67680bd42964457294a7587ab8c4fa813c172f16faebd6f151db39369,
// mask: f034b8ff2cbd2729a7c19c0cc59a053fcbe1123f10acb0ec9e86bf122f0d3b12,
// txid: 0x5e2ca0b269c56e370cb8b243f4a7c5656195471dcb643a99036050fbb212f248,
// unlocked: false,
// },
// OutKey {
// height: 108,
// key: f8cf697bb285cbd61586543b2cd9e70f6b030348586d6e24c2a82cd8a4b4c8db,
// mask: 9ad72a2f1867a99367f045a512b7474234e0e08e39ba4f8fbd961d076348ee28,
// txid: 0x9a27def957d31482922cfd98a8422e92eba2a40f5ea1c285b5ac708b359f1a8d,
// unlocked: false,
// },
// OutKey {
// height: 109,
// key: 5b90003c16b591249d968cf401cd5ea99392963b401476746bad28606362bd42,
// mask: 69a62e221e990bc91453dfaee01dfc307dff680a6b270944598014df32097563,
// txid: 0xfc6b1a98cadbf19e84a0dccff53c34dbd4cf1e27c3558c913f7b3512d57d42b8,
// unlocked: false,
// },
// OutKey {
// height: 113,
// key: ad46eef99661c1e93ba517d3e541eebf9c42ba015566ff5dcc3a689edaf8f2ac,
// mask: b3012a4a5c0b3b465246e9671b7cdb84f817bedcc1ab9015aeff1f6ccffebb0c,
// txid: 0xf8a557dd14b6714eab5661b35944c4b09d0f8a9ef82b31ffb19244f7dfd127da,
// unlocked: false,
// },
// OutKey {
// height: 116,
// key: 76f445a4ff9a957d979f910040938a25b01759c7aad3605193502b35cdc8ff58,
// mask: a2091a955e819696b4526ae54f7dcf69f9fe7a42a0edcdb69f787437fc73244d,
// txid: 0xd5d82405a655ebf721e32c8ef2f8b77f2476dd7cbdb06c05b9735abdf9a2a927,
// unlocked: true,
// },
// ],
let relative_key_offsets = to_relative_offsets(&key_offsets); let relative_key_offsets = to_relative_offsets(&key_offsets);
let amount = 10_000_000; let amount = 10_000_000;
let fee = 10_000; let fee = 10_000;
// TODO: Pay lock amount (= amount + fee) to shared address (s_prime_a + s_b) // TODO: Pay lock amount (= amount + fee) to shared address (s_prime_a + s_b)
let (bulletproof, out_pk, _) = monero::make_bulletproof(&mut rng, &[amount]).unwrap(); let (bulletproof, out_pk, out_blindings) =
monero::make_bulletproof(&mut rng, &[amount]).unwrap();
let out_pk = out_pk let out_pk = out_pk
.iter() .iter()
.map(|c| monero::util::ringct::CtKey { .map(|c| monero::util::ringct::CtKey {
@ -177,6 +106,10 @@ async fn monerod_integration_test() {
}) })
.collect(); .collect();
let target_address = "498AVruCDWgP9Az9LjMm89VWjrBrSZ2W2K3HFBiyzzrRjUJWUcCVxvY1iitfuKoek2FdX6MKGAD9Qb1G1P8QgR5jPmmt3Vj".parse::<monero::Address>().unwrap();
let ecdh_key = PrivateKey::random(&mut rng);
let prefix = TransactionPrefix { let prefix = TransactionPrefix {
version: VarInt(2), version: VarInt(2),
unlock_time: Default::default(), unlock_time: Default::default(),
@ -185,8 +118,20 @@ async fn monerod_integration_test() {
key_offsets: relative_key_offsets, key_offsets: relative_key_offsets,
k_image: todo!(), k_image: todo!(),
}], }],
outputs: vec![], // 498AVruCDWgP9Az9LjMm89VWjrBrSZ2W2K3HFBiyzzrRjUJWUcCVxvY1iitfuKoek2FdX6MKGAD9Qb1G1P8QgR5jPmmt3Vj outputs: vec![TxOut {
extra: Default::default(), amount: VarInt(0),
target: TxOutTarget::ToKey {
key: KeyGenerator::from_random(
target_address.public_view,
target_address.public_spend,
ecdh_key,
)
.one_time_key(0),
},
}],
extra: ExtraField(vec![SubField::TxPublicKey(PublicKey::from_private_key(
&ecdh_key,
))]),
}; };
let (adaptor_sig, adaptor) = let (adaptor_sig, adaptor) =
@ -210,10 +155,12 @@ async fn monerod_integration_test() {
bulletproofs: vec![bulletproof], bulletproofs: vec![bulletproof],
MGs: Vec::new(), MGs: Vec::new(),
Clsags: vec![sig.into()], Clsags: vec![sig.into()],
pseudo_outs: todo!(), pseudo_outs: todo!("out_blindings + pseudo_outs == 0, 1 pseudo out per input: calculated by input amount * G + H * 'random blinding factor'"),
}), }),
}, },
}; };
todo!("broadcast transaction")
} }
fn to_relative_offsets(offsets: &[VarInt]) -> Vec<VarInt> { fn to_relative_offsets(offsets: &[VarInt]) -> Vec<VarInt> {

View File

@ -10,6 +10,7 @@ monero = "0.12"
monero-rpc = { path = "../monero-rpc" } monero-rpc = { path = "../monero-rpc" }
rand = "0.7" rand = "0.7"
curve25519-dalek = "3" curve25519-dalek = "3"
async-trait = "0.1"
[dev-dependencies] [dev-dependencies]
monero-harness = { path = "../monero-harness" } monero-harness = { path = "../monero-harness" }

View File

@ -3,39 +3,49 @@ use monero::consensus::encode::VarInt;
use monero::cryptonote::hash::Hashable; use monero::cryptonote::hash::Hashable;
use monero_rpc::monerod; use monero_rpc::monerod;
use monero_rpc::monerod::{GetBlockResponse, MonerodRpc as _}; use monero_rpc::monerod::{GetBlockResponse, MonerodRpc as _};
use rand::{Rng, RngCore, CryptoRng}; use rand::{CryptoRng, Rng, RngCore};
pub struct Wallet { pub struct Wallet {
client: monerod::Client, key: monero::KeyPair,
key: monero::KeyPair
} }
impl Wallet { impl Wallet {
pub fn new_random<R: CryptoRng + RngCore>(client: monerod::Client, rng: &mut R) -> Self { pub fn new_random<R: CryptoRng + RngCore>(rng: &mut R) -> Self {
Self { Self {
client,
key: monero::KeyPair { key: monero::KeyPair {
view: monero::PrivateKey::from_scalar(curve25519_dalek::scalar::Scalar::random(rng)), view: monero::PrivateKey::from_scalar(curve25519_dalek::scalar::Scalar::random(
spend: monero::PrivateKey::from_scalar(curve25519_dalek::scalar::Scalar::random(rng)), rng,
} )),
spend: monero::PrivateKey::from_scalar(curve25519_dalek::scalar::Scalar::random(
rng,
)),
},
} }
} }
pub fn get_address(&self, network: monero::Network) -> monero::Address { pub fn get_address(&self, network: monero::Network) -> monero::Address {
monero::Address::from_keypair(network, &self.key) monero::Address::from_keypair(network, &self.key)
} }
}
#[async_trait::async_trait]
pub trait MonerodClientExt {
async fn calculate_key_offset_boundaries(&self) -> Result<(VarInt, VarInt)>;
}
#[async_trait::async_trait]
impl MonerodClientExt for monerod::Client {
/// Chooses 10 random key offsets for use within a new confidential /// Chooses 10 random key offsets for use within a new confidential
/// transactions. /// transactions.
/// ///
/// Choosing these offsets randomly is not ideal for privacy, instead they /// Choosing these offsets randomly is not ideal for privacy, instead they
/// should be chosen in a way that mimics a real spending pattern as much as /// should be chosen in a way that mimics a real spending pattern as much as
/// possible. /// possible.
pub async fn calculate_key_offset_boundaries(&self) -> Result<(VarInt, VarInt)> { async fn calculate_key_offset_boundaries(&self) -> Result<(VarInt, VarInt)> {
let latest_block = self.client.get_block_count().await?; let latest_block = self.get_block_count().await?;
let latest_spendable_block = latest_block.count - 10; let latest_spendable_block = latest_block.count - 10;
let block: GetBlockResponse = self.client.get_block(latest_spendable_block).await?; let block: GetBlockResponse = self.get_block(latest_spendable_block).await?;
let tx_hash = block let tx_hash = block
.blob .blob
@ -44,7 +54,7 @@ impl Wallet {
.copied() .copied()
.unwrap_or_else(|| block.blob.miner_tx.hash()); .unwrap_or_else(|| block.blob.miner_tx.hash());
let indices = self.client.get_o_indexes(tx_hash).await?; let indices = self.get_o_indexes(tx_hash).await?;
let last_index = indices let last_index = indices
.o_indexes .o_indexes
@ -73,7 +83,7 @@ mod tests {
rpc_client.generateblocks(150, "498AVruCDWgP9Az9LjMm89VWjrBrSZ2W2K3HFBiyzzrRjUJWUcCVxvY1iitfuKoek2FdX6MKGAD9Qb1G1P8QgR5jPmmt3Vj".to_owned()).await.unwrap(); rpc_client.generateblocks(150, "498AVruCDWgP9Az9LjMm89VWjrBrSZ2W2K3HFBiyzzrRjUJWUcCVxvY1iitfuKoek2FdX6MKGAD9Qb1G1P8QgR5jPmmt3Vj".to_owned()).await.unwrap();
let wallet = Wallet { let wallet = Wallet {
client: rpc_client.clone(), client: rpc_client.clone(),
key: todo!() key: todo!(),
}; };
let (lower, upper) = wallet.calculate_key_offset_boundaries().await.unwrap(); let (lower, upper) = wallet.calculate_key_offset_boundaries().await.unwrap();

View File

@ -165,7 +165,9 @@ impl State0 {
let v = self.v_a + msg.v_b; let v = self.v_a + msg.v_b;
Ok((msg.swap_id, State1 { Ok((
msg.swap_id,
State1 {
a: self.a, a: self.a,
B: msg.B, B: msg.B,
s_a: self.s_a, s_a: self.s_a,
@ -183,7 +185,8 @@ impl State0 {
refund_address: msg.refund_address, refund_address: msg.refund_address,
redeem_address: self.redeem_address, redeem_address: self.redeem_address,
punish_address: self.punish_address, punish_address: self.punish_address,
})) },
))
} }
} }

View File

@ -155,13 +155,16 @@ async fn init_containers(cli: &Cli) -> (Monero, Containers<'_>) {
.await .await
.unwrap(); .unwrap();
(monero, Containers { (
monero,
Containers {
bitcoind_url, bitcoind_url,
bitcoind, bitcoind,
monerod_container, monerod_container,
monero_wallet_rpc_containers, monero_wallet_rpc_containers,
electrs, electrs,
}) },
)
} }
async fn init_bitcoind_container( async fn init_bitcoind_container(

View File

@ -516,7 +516,9 @@ impl Header {
pub fn username_bytes(&self) -> Option<&[u8]> { pub fn username_bytes(&self) -> Option<&[u8]> {
if let Some(ustar) = self.as_ustar() { if let Some(ustar) = self.as_ustar() {
Some(ustar.username_bytes()) Some(ustar.username_bytes())
} else { self.as_gnu().map(|gnu| gnu.username_bytes()) } } else {
self.as_gnu().map(|gnu| gnu.username_bytes())
}
} }
/// Sets the username inside this header. /// Sets the username inside this header.