Explorar el Código

note: Implement memo field in encrypted notes.

This can store arbitrary data.
parazyd hace 4 años
padre
commit
1e109e3edc
Se han modificado 8 ficheros con 35 adiciones y 24 borrados
  1. 2 1
      script/sql/coins.sql
  2. 1 1
      src/crypto/mod.rs
  3. 9 9
      src/crypto/note.rs
  4. 1 1
      src/node/client.rs
  5. 7 2
      src/node/state.rs
  6. 1 1
      src/tx/builder.rs
  7. 1 1
      src/tx/mod.rs
  8. 13 8
      src/wallet/walletdb.rs

+ 2 - 1
script/sql/coins.sql

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

+ 1 - 1
src/crypto/mod.rs

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

+ 9 - 9
src/crypto/note.rs

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

+ 1 - 1
src/node/client.rs

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

+ 7 - 2
src/node/state.rs

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

+ 1 - 1
src/tx/builder.rs

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

+ 1 - 1
src/tx/mod.rs

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

+ 13 - 8
src/wallet/walletdb.rs

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