mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
note: Implement memo field in encrypted notes.
This can store arbitrary data.
This commit is contained in:
@@ -9,5 +9,6 @@ CREATE TABLE IF NOT EXISTS coins(
|
||||
secret BLOB NOT NULL,
|
||||
is_spent BOOLEAN NOT NULL,
|
||||
nullifier BLOB NOT NULL,
|
||||
leaf_position BLOB NOT NULL
|
||||
leaf_position BLOB NOT NULL,
|
||||
memo BLOB
|
||||
);
|
||||
|
||||
@@ -32,7 +32,7 @@ use crate::{
|
||||
use keypair::SecretKey;
|
||||
use std::io;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SerialEncodable, SerialDecodable)]
|
||||
pub struct OwnCoin {
|
||||
pub coin: coin::Coin,
|
||||
pub note: note::Note,
|
||||
|
||||
@@ -11,12 +11,9 @@ use crate::{
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
/// Plaintext size is serial + value + token_id + coin_blind + value_blind
|
||||
pub const NOTE_PLAINTEXT_SIZE: usize = 32 + 8 + 32 + 32 + 32 + 32;
|
||||
pub const AEAD_TAG_SIZE: usize = 16;
|
||||
pub const ENC_CIPHERTEXT_SIZE: usize = NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SerialEncodable, SerialDecodable)]
|
||||
pub struct Note {
|
||||
pub serial: DrkSerial,
|
||||
pub value: u64,
|
||||
@@ -24,6 +21,7 @@ pub struct Note {
|
||||
pub coin_blind: DrkCoinBlind,
|
||||
pub value_blind: DrkValueBlind,
|
||||
pub token_blind: DrkValueBlind,
|
||||
pub memo: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Note {
|
||||
@@ -36,12 +34,12 @@ impl Note {
|
||||
let mut input = Vec::new();
|
||||
self.encode(&mut input)?;
|
||||
|
||||
let mut ciphertext = [0u8; ENC_CIPHERTEXT_SIZE];
|
||||
let mut ciphertext = vec![0; input.len() + AEAD_TAG_SIZE];
|
||||
assert_eq!(
|
||||
ChachaPolyIetf::aead_cipher()
|
||||
.seal_to(&mut ciphertext, &input, &[], key.as_ref(), &[0u8; 12])
|
||||
.unwrap(),
|
||||
ENC_CIPHERTEXT_SIZE
|
||||
input.len() + AEAD_TAG_SIZE
|
||||
);
|
||||
|
||||
Ok(EncryptedNote { ciphertext, ephem_public })
|
||||
@@ -50,7 +48,7 @@ impl Note {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
|
||||
pub struct EncryptedNote {
|
||||
ciphertext: [u8; ENC_CIPHERTEXT_SIZE],
|
||||
ciphertext: Vec<u8>,
|
||||
ephem_public: PublicKey,
|
||||
}
|
||||
|
||||
@@ -59,12 +57,12 @@ impl EncryptedNote {
|
||||
let shared_secret = sapling_ka_agree(secret, &self.ephem_public);
|
||||
let key = kdf_sapling(&shared_secret, &self.ephem_public);
|
||||
|
||||
let mut plaintext = [0; ENC_CIPHERTEXT_SIZE];
|
||||
let mut plaintext = vec![0; self.ciphertext.len()];
|
||||
assert_eq!(
|
||||
ChachaPolyIetf::aead_cipher()
|
||||
.open_to(&mut plaintext, &self.ciphertext, &[], key.as_ref(), &[0u8; 12])
|
||||
.map_err(|_| Error::NoteDecryptionFailed)?,
|
||||
NOTE_PLAINTEXT_SIZE
|
||||
self.ciphertext.len() - AEAD_TAG_SIZE
|
||||
);
|
||||
|
||||
Note::decode(&plaintext[..])
|
||||
@@ -86,6 +84,7 @@ mod tests {
|
||||
coin_blind: DrkCoinBlind::random(&mut OsRng),
|
||||
value_blind: DrkValueBlind::random(&mut OsRng),
|
||||
token_blind: DrkValueBlind::random(&mut OsRng),
|
||||
memo: vec![32, 223, 231, 3, 1, 1],
|
||||
};
|
||||
|
||||
let keypair = Keypair::random(&mut OsRng);
|
||||
@@ -95,5 +94,6 @@ mod tests {
|
||||
assert_eq!(note.value, note2.value);
|
||||
assert_eq!(note.token_id, note2.token_id);
|
||||
assert_eq!(note.token_blind, note2.token_blind);
|
||||
assert_eq!(note.memo, note2.memo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ impl Client {
|
||||
leaf_position,
|
||||
merkle_path,
|
||||
secret: own_coin.secret,
|
||||
note: own_coin.note,
|
||||
note: own_coin.note.clone(),
|
||||
};
|
||||
|
||||
inputs.push(input);
|
||||
|
||||
@@ -164,8 +164,13 @@ impl State {
|
||||
debug!(target: "state_apply", "Received a coin: amount {}", note.value);
|
||||
let leaf_position = self.tree.witness().unwrap();
|
||||
let nullifier = Nullifier::new(*secret, note.serial);
|
||||
let own_coin =
|
||||
OwnCoin { coin, note, secret: *secret, nullifier, leaf_position };
|
||||
let own_coin = OwnCoin {
|
||||
coin,
|
||||
note: note.clone(),
|
||||
secret: *secret,
|
||||
nullifier,
|
||||
leaf_position,
|
||||
};
|
||||
|
||||
// TODO: FIXME: BUG check values inside the note are correct
|
||||
// We need to hash them all and check them against the coin
|
||||
|
||||
@@ -145,7 +145,6 @@ impl TransactionBuilder {
|
||||
)?;
|
||||
|
||||
// Encrypted note
|
||||
|
||||
let note = Note {
|
||||
serial,
|
||||
value: output.value,
|
||||
@@ -153,6 +152,7 @@ impl TransactionBuilder {
|
||||
coin_blind,
|
||||
value_blind,
|
||||
token_blind,
|
||||
memo: vec![],
|
||||
};
|
||||
|
||||
let encrypted_note = note.encrypt(&output.public)?;
|
||||
|
||||
@@ -48,7 +48,7 @@ pub struct TransactionClearInput {
|
||||
pub token_blind: DrkValueBlind,
|
||||
/// Public key for the signature
|
||||
pub signature_public: PublicKey,
|
||||
/// Input's signature
|
||||
/// Transaction signature
|
||||
pub signature: schnorr::Signature,
|
||||
}
|
||||
|
||||
|
||||
@@ -270,7 +270,8 @@ impl WalletDb {
|
||||
let value = deserialize(row.get("value"))?;
|
||||
let token_id = deserialize(row.get("token_id"))?;
|
||||
let token_blind = deserialize(row.get("token_blind"))?;
|
||||
let note = Note { serial, value, token_id, coin_blind, value_blind, token_blind };
|
||||
let memo = deserialize(row.get("memo"))?;
|
||||
let note = Note { serial, value, token_id, coin_blind, value_blind, token_blind, memo };
|
||||
|
||||
let secret = deserialize(row.get("secret"))?;
|
||||
let nullifier = deserialize(row.get("nullifier"))?;
|
||||
@@ -329,7 +330,8 @@ impl WalletDb {
|
||||
let value = deserialize(row.get("value"))?;
|
||||
let token_id = deserialize(row.get("token_id"))?;
|
||||
let token_blind = deserialize(row.get("token_blind"))?;
|
||||
let note = Note { serial, value, token_id, coin_blind, value_blind, token_blind };
|
||||
let memo = deserialize(row.get("memo"))?;
|
||||
let note = Note { serial, value, token_id, coin_blind, value_blind, token_blind, memo };
|
||||
|
||||
let secret = deserialize(row.get("secret"))?;
|
||||
let nullifier = deserialize(row.get("nullifier"))?;
|
||||
@@ -356,15 +358,16 @@ impl WalletDb {
|
||||
let secret = serialize(&own_coin.secret);
|
||||
let nullifier = serialize(&own_coin.nullifier);
|
||||
let leaf_position = serialize(&own_coin.leaf_position);
|
||||
let memo = serialize(&own_coin.note.memo);
|
||||
let is_spent: u8 = 0;
|
||||
|
||||
let mut conn = self.conn.acquire().await?;
|
||||
sqlx::query(
|
||||
"INSERT OR REPLACE INTO coins
|
||||
(coin, serial, coin_blind, valcom_blind, token_blind, value,
|
||||
token_id, secret, is_spent, nullifier, leaf_position)
|
||||
token_id, secret, is_spent, nullifier, leaf_position, memo)
|
||||
VALUES
|
||||
(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11);",
|
||||
(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12);",
|
||||
)
|
||||
.bind(coin)
|
||||
.bind(serial)
|
||||
@@ -377,6 +380,7 @@ impl WalletDb {
|
||||
.bind(is_spent)
|
||||
.bind(nullifier)
|
||||
.bind(leaf_position)
|
||||
.bind(memo)
|
||||
.execute(&mut conn)
|
||||
.await?;
|
||||
|
||||
@@ -510,6 +514,7 @@ mod tests {
|
||||
coin_blind: DrkCoinBlind::random(&mut OsRng),
|
||||
value_blind: DrkValueBlind::random(&mut OsRng),
|
||||
token_blind: DrkValueBlind::random(&mut OsRng),
|
||||
memo: vec![],
|
||||
};
|
||||
|
||||
let coin = Coin(pallas::Base::random(&mut OsRng));
|
||||
@@ -541,19 +546,19 @@ mod tests {
|
||||
let c3 = dummy_coin(&keypair.secret, 11, &token_id);
|
||||
|
||||
// put_own_coin()
|
||||
wallet.put_own_coin(c0).await?;
|
||||
wallet.put_own_coin(c0.clone()).await?;
|
||||
tree1.append(&MerkleNode::from_coin(&c0.coin));
|
||||
tree1.witness();
|
||||
|
||||
wallet.put_own_coin(c1).await?;
|
||||
wallet.put_own_coin(c1.clone()).await?;
|
||||
tree1.append(&MerkleNode::from_coin(&c1.coin));
|
||||
tree1.witness();
|
||||
|
||||
wallet.put_own_coin(c2).await?;
|
||||
wallet.put_own_coin(c2.clone()).await?;
|
||||
tree1.append(&MerkleNode::from_coin(&c2.coin));
|
||||
tree1.witness();
|
||||
|
||||
wallet.put_own_coin(c3).await?;
|
||||
wallet.put_own_coin(c3.clone()).await?;
|
||||
tree1.append(&MerkleNode::from_coin(&c3.coin));
|
||||
tree1.witness();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user