Skip to content

Commit

Permalink
Merge pull request bitcoin#37 from LNP-BP/feat-wallet
Browse files Browse the repository at this point in the history
Functions required for full wallet support
  • Loading branch information
dr-orlovsky committed May 8, 2020
2 parents 47854ca + 56c790b commit 0b785e4
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 15 deletions.
36 changes: 35 additions & 1 deletion src/csv/serialize/commitment/primitives.rs
Expand Up @@ -16,6 +16,7 @@ use std::{io, str, ops::Deref};

use num_traits::{ToPrimitive, FromPrimitive};
use bitcoin::{
secp256k1,
hash_types::Txid,
util::uint::{Uint128, Uint256},
consensus::encode as consensus
Expand Down Expand Up @@ -149,6 +150,40 @@ impl Commitment for String {
}
}

impl Commitment for secp256k1::PublicKey {
fn commitment_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(e.write(&self.serialize())?)
}

fn commitment_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
let mut buf = [0u8; secp256k1::constants::PUBLIC_KEY_SIZE];
d.read_exact(&mut buf);
Ok(Self::from_slice(&buf).map_err(|_| Error::DataIntegrityError)?)
}
}

impl Commitment for secp256k1::Signature {
fn commitment_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(e.write(&self.serialize_compact())?)
}

fn commitment_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
let mut buf = [0u8; secp256k1::constants::PUBLIC_KEY_SIZE];
d.read_exact(&mut buf);
Ok(Self::from_compact(&buf).map_err(|_| Error::DataIntegrityError)?)
}
}

impl Commitment for bitcoin::Network {
fn commitment_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(self.magic().commitment_serialize(&mut e)?)
}

fn commitment_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
Ok(Self::from_magic(u32::commitment_deserialize(&mut d)?).ok_or(Error::ValueOutOfRange)?)
}
}

impl Commitment for ShortId {
fn commitment_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
self.into_u64().commitment_serialize(&mut e)
Expand All @@ -159,7 +194,6 @@ impl Commitment for ShortId {
}
}


// Tests
#[cfg(test)]
mod tests {
Expand Down
29 changes: 15 additions & 14 deletions src/csv/serialize/mod.rs
Expand Up @@ -22,37 +22,38 @@ pub use network::*;
pub use storage::*;


use std::{str, string, convert::From};
use std::{io, str, string, convert::From};

#[derive(Debug, Display)]
#[derive(Debug, Display, From)]
#[display_from(Debug)]
#[non_exhaustive]
pub enum Error {
#[derive_from]
IoError(io::Error),

#[derive_from]
BitcoinConsensus(bitcoin::consensus::encode::Error),

EnumValueUnknown(u8),

EnumValueOverflow,

#[derive_from]
Utf8Error(str::Utf8Error),

ValueOutOfRange,

WrongOptionalEncoding,

WrongDataSize { expected: usize, found: usize },

ParseFailed(&'static str),
}

impl From<str::Utf8Error> for Error {
fn from(err: str::Utf8Error) -> Self {
Self::Utf8Error(err)
}
DataIntegrityError,
}

impl From<string::FromUtf8Error> for Error {
fn from(err: string::FromUtf8Error) -> Self {
Self::Utf8Error(err.utf8_error())
}
}

impl From<bitcoin::consensus::encode::Error> for Error {
#[inline]
fn from(err: bitcoin::consensus::encode::Error) -> Self {
Error::BitcoinConsensus(err)
}
}
116 changes: 116 additions & 0 deletions src/csv/serialize/network.rs
Expand Up @@ -12,6 +12,7 @@
// If not, see <https://opensource.org/licenses/MIT>.

use std::{io, collections::HashMap};
use bitcoin::{secp256k1, util::bip32};

use super::Error;
use crate::bp;
Expand Down Expand Up @@ -74,6 +75,9 @@ network_serialize_from_commitment!(&[u8]);
network_serialize_from_commitment!(Box<[u8]>);
network_serialize_from_commitment!(&str);
network_serialize_from_commitment!(String);
network_serialize_from_commitment!(secp256k1::PublicKey);
network_serialize_from_commitment!(secp256k1::Signature);
network_serialize_from_commitment!(bitcoin::Network);
network_serialize_from_commitment!(bp::ShortId);


Expand Down Expand Up @@ -171,6 +175,118 @@ impl<A, B> Network for (A, B) where A: Network, B: Network {
}


impl Network for bitcoin::PublicKey {
fn network_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(if self.compressed {
e.write(&self.key.serialize())?
} else {
e.write(&self.key.serialize_uncompressed())?
})
}

fn network_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
let marker = u8::network_deserialize(&mut d)?;
match marker {
0x04 => {
let mut buf = [0u8; secp256k1::constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
buf[0] = marker;
d.read_exact(&mut buf[1..]);
Ok(Self::from_slice(&buf).map_err(|_| Error::DataIntegrityError)?)
},
0x03 | 0x02 => {
let mut buf = [0u8; secp256k1::constants::PUBLIC_KEY_SIZE];
buf[0] = marker;
d.read_exact(&mut buf[1..]);
Ok(Self::from_slice(&buf).map_err(|_| Error::DataIntegrityError)?)
}
_ => Err(Error::DataIntegrityError),
}
}
}

impl Network for bip32::ChildNumber {
fn network_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
let (t, index) = match self {
bip32::ChildNumber::Normal { index } => (0u8, index),
bip32::ChildNumber::Hardened { index } => (1u8, index),
};
Ok(
t.network_serialize(&mut e)? +
index.network_serialize(&mut e)?
)
}

fn network_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
let t = u8::network_deserialize(&mut d)?;
let index = u32::network_deserialize(&mut d)?;
Ok(match t {
0 => bip32::ChildNumber::Normal { index },
1 => bip32::ChildNumber::Hardened { index },
x => Err(Error::EnumValueUnknown(x))?,
})
}
}

impl Network for bip32::DerivationPath {
fn network_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
let buf: Vec<bip32::ChildNumber> = self.into_iter().map(bip32::ChildNumber::clone).collect();
Ok(buf.network_serialize(&mut e)?)
}

fn network_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
Ok(Self::from(Vec::<bip32::ChildNumber>::network_deserialize(&mut d)?))
}
}

impl Network for bip32::ChainCode {
fn network_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(e.write(self.as_bytes())?)
}

fn network_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
let mut buf = [0u8; 32];
d.read_exact(&mut buf);
Ok(Self::from(&buf[..]))
}
}

impl Network for bip32::Fingerprint {
fn network_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(e.write(self.as_bytes())?)
}

fn network_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
let mut buf = [0u8; 4];
d.read_exact(&mut buf);
Ok(Self::from(&buf[..]))
}
}

impl Network for bip32::ExtendedPubKey {
fn network_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(
self.network.network_serialize(&mut e)? +
self.depth.network_serialize(&mut e)? +
self.parent_fingerprint.network_serialize(&mut e)? +
self.child_number.network_serialize(&mut e)? +
self.public_key.network_serialize(&mut e)? +
self.chain_code.network_serialize(&mut e)?
)
}

fn network_deserialize<D: io::Read>(mut d: D) -> Result<Self, Error> {
Ok(Self {
network: bitcoin::Network::network_deserialize(&mut d)?,
depth: u8::network_deserialize(&mut d)?,
parent_fingerprint: bip32::Fingerprint::network_deserialize(&mut d)?,
child_number: bip32::ChildNumber::network_deserialize(&mut d)?,
public_key: bitcoin::PublicKey::network_deserialize(&mut d)?,
chain_code: bip32::ChainCode::network_deserialize(&mut d)?,
})
}
}


#[inline]
pub fn network_serialize<T: Network>(data: &T) -> Result<Vec<u8>, Error> {
let mut encoder = io::Cursor::new(vec![]);
Expand Down
9 changes: 9 additions & 0 deletions src/rgb/mod.rs
Expand Up @@ -25,6 +25,8 @@ pub mod transition;
pub mod serialize;
pub mod commit;

mod proof;


pub use schemata::*;

Expand All @@ -34,3 +36,10 @@ pub use metadata::Metadata;
pub use script::Script;
pub use seal::Seal;
pub use transition::Transition;

pub use proof::*;


use bitcoin::hashes::{Hash, sha256d};

hash_newtype!(ContractId, sha256d::Hash, 32, doc="Double-sha256 hash of the genesis transition");
80 changes: 80 additions & 0 deletions src/rgb/proof.rs
@@ -0,0 +1,80 @@
// LNP/BP Rust Library
// Written in 202 by
// Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the MIT License
// along with this software.
// If not, see <https://opensource.org/licenses/MIT>.


use bitcoin::Txid;
use bitcoin::hashes::sha256d;

use super::{ContractId, data::amount, Seal, Transition};


///! Structures required for full validation of a given state transfer

/// Part of the LNPBP-5 multimessage commitment
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display)]
#[display_from(Debug)]
pub enum CommitmentProofItem {
/// We commit to the item at this place
Placeholder,
/// Some other commitment
Hash(sha256d::Hash),
}

/// Whole LNPBP-5 multimessage commitment as a vector of individual commitments
pub type CommitmentProof = Vec<CommitmentProofItem>;

/// Proves information on how a given transition committment is placed withing
/// some LNPBP-5 multimessage commitment
#[derive(Clone, PartialEq, Debug, Display)]
#[display_from(Debug)]
pub struct MultimessageReveal {
pub transition: Transition,
pub commitment_proof: CommitmentProof
}

/// Proves source of the state data.
/// The state is represented by a raw non-encrypted data is not provided
/// as a part of the proof, so we don't need this option here.
#[non_exhaustive]
#[derive(Clone, PartialEq, Debug, Display)]
#[display_from(Debug)]
pub enum DataReveal {
/// Confidential amount disclosure
Balance(amount::Proof),
}

/// Provides source for the seal data
#[derive(Clone, PartialEq, Debug, Display)]
#[display_from(Debug)]
pub struct StateReveal {
/// Seal definition that contains an assigned state
pub seal: Seal,
/// Assigned state source data
pub data_proof: DataReveal,
}

#[derive(Clone, PartialEq, Debug, Display)]
#[display_from(Debug)]
pub struct Proof {
/// Contract id
pub contract_id: ContractId,

/// History of state transition (graph serialized in a linear vec)
pub transition_history: Vec<MultimessageReveal>,

/// Reveals information all all confidential states
pub state_proofs: Vec<StateReveal>,

/// Optional list of the witness transaction ids
pub witness_txids: Option<Vec<Txid>>,
}
2 changes: 2 additions & 0 deletions src/rgb/transition.rs
Expand Up @@ -14,6 +14,8 @@

use super::{State, Metadata, Script};

#[derive(Clone, PartialEq, Debug, Display)]
#[display_from(Debug)]
pub struct Transition {
pub meta: Metadata,
pub state: State,
Expand Down

0 comments on commit 0b785e4

Please sign in to comment.