note: Implement memo field in encrypted notes.

This can store arbitrary data.
This commit is contained in:
parazyd
2022-08-09 17:14:52 +02:00
parent 02e9d65e1f
commit 1e109e3edc
8 changed files with 35 additions and 24 deletions

View File

@@ -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
);

View File

@@ -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,

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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)?;

View File

@@ -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,
}

View File

@@ -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();