Implements low-level transparent components #45
3 changed files with 72 additions and 8 deletions
|
@ -36,6 +36,7 @@ use zcash_primitives::{
|
||||||
Bundle as TransparentBundle,
|
Bundle as TransparentBundle,
|
||||||
TxIn,
|
TxIn,
|
||||||
TxOut,
|
TxOut,
|
||||||
|
OutPoint,
|
||||||
Authorized
|
Authorized
|
||||||
},
|
},
|
||||||
sapling::{
|
sapling::{
|
||||||
|
@ -246,6 +247,7 @@ impl<RW> ToHaskell<RW> for Htx {
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct HTBundle {
|
pub struct HTBundle {
|
||||||
|
empty: bool,
|
||||||
vin: Vec<HTxIn>,
|
vin: Vec<HTxIn>,
|
||||||
vout: Vec<HTxOut>,
|
vout: Vec<HTxOut>,
|
||||||
coinbase: bool
|
coinbase: bool
|
||||||
|
@ -260,13 +262,13 @@ impl<RW> ToHaskell<RW> for HTBundle {
|
||||||
|
|
||||||
impl HTBundle {
|
impl HTBundle {
|
||||||
pub fn from_bundle(b: &TransparentBundle<Authorized>) -> HTBundle {
|
pub fn from_bundle(b: &TransparentBundle<Authorized>) -> HTBundle {
|
||||||
HTBundle { vin: b.vin.iter().map(HTxIn::pack).collect() , vout: b.vout.iter().map(HTxOut::pack).collect(), coinbase: b.is_coinbase()}
|
HTBundle {empty: false, vin: b.vin.iter().map(HTxIn::pack).collect() , vout: b.vout.iter().map(HTxOut::pack).collect(), coinbase: b.is_coinbase()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct HTxIn {
|
pub struct HTxIn {
|
||||||
outpoint: u32,
|
outpoint: Houtpoint,
|
||||||
script: Vec<u8>,
|
script: Vec<u8>,
|
||||||
sequence: u32
|
sequence: u32
|
||||||
}
|
}
|
||||||
|
@ -280,7 +282,7 @@ impl<RW> ToHaskell<RW> for HTxIn {
|
||||||
|
|
||||||
impl HTxIn {
|
impl HTxIn {
|
||||||
pub fn pack(t: &TxIn<Authorized>) -> HTxIn {
|
pub fn pack(t: &TxIn<Authorized>) -> HTxIn {
|
||||||
return HTxIn { outpoint: t.prevout.n(), script: t.script_sig.0.clone(), sequence: t.sequence}
|
return HTxIn { outpoint: Houtpoint::pack(&t.prevout), script: t.script_sig.0.clone(), sequence: t.sequence}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +305,25 @@ impl HTxOut {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
|
pub struct Houtpoint {
|
||||||
|
hash: Vec<u8>,
|
||||||
|
index: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<RW> ToHaskell<RW> for Houtpoint {
|
||||||
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
|
self.serialize(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Houtpoint {
|
||||||
|
pub fn pack(o: &OutPoint) -> Houtpoint {
|
||||||
|
return Houtpoint {hash: o.hash().to_vec() , index: o.n() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct Hufvk {
|
pub struct Hufvk {
|
||||||
net: u8,
|
net: u8,
|
||||||
|
@ -651,11 +672,20 @@ pub extern "C" fn rust_wrapper_tx_read(
|
||||||
let parsed_tx = Transaction::read(&mut tx_reader, Nu5);
|
let parsed_tx = Transaction::read(&mut tx_reader, Nu5);
|
||||||
match parsed_tx {
|
match parsed_tx {
|
||||||
Ok(t) => {
|
Ok(t) => {
|
||||||
let h = Htx {txid: t.txid().as_ref().to_vec(), locktime: t.lock_time(), expiry: u32::from(t.expiry_height()), t_bundle: HTBundle::from_bundle(t.transparent_bundle().unwrap()) };
|
let tb = t.transparent_bundle();
|
||||||
|
match tb {
|
||||||
|
Some(my_tb) => {
|
||||||
|
let h = Htx {txid: t.txid().as_ref().to_vec(), locktime: t.lock_time(), expiry: u32::from(t.expiry_height()), t_bundle: HTBundle::from_bundle(my_tb) };
|
||||||
marshall_to_haskell_var(&h, out, out_len, RW);
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
},
|
},
|
||||||
|
None => {
|
||||||
|
let h0 = Htx {txid: t.txid().as_ref().to_vec(), locktime: t.lock_time(), expiry: u32::from(t.expiry_height()), t_bundle: HTBundle {empty: true, vin: vec![HTxIn {outpoint: Houtpoint {hash: vec![0], index: 0}, script: vec![0], sequence: 0}], vout: vec![HTxOut {amt: 0, script: vec![0]}], coinbase: true} };
|
||||||
|
marshall_to_haskell_var(&h0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
let h0 = Htx {txid: vec![0], locktime: 0, expiry: 0, t_bundle: HTBundle {vin: vec![HTxIn {outpoint: 0, script: vec![0], sequence: 0}], vout: vec![HTxOut {amt: 0, script: vec![0]}], coinbase: true} };
|
let h0 = Htx {txid: vec![0], locktime: 0, expiry: 0, t_bundle: HTBundle {empty: true, vin: vec![HTxIn {outpoint: Houtpoint {hash: vec![0], index: 0}, script: vec![0], sequence: 0}], vout: vec![HTxOut {amt: 0, script: vec![0]}], coinbase: true} };
|
||||||
marshall_to_haskell_var(&h0, out, out_len, RW);
|
marshall_to_haskell_var(&h0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import Data.Aeson
|
||||||
import qualified Data.ByteArray as BA
|
import qualified Data.ByteArray as BA
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Char8 as C
|
import qualified Data.ByteString.Char8 as C
|
||||||
|
import qualified Data.ByteString.Lazy.UTF8 as US
|
||||||
import Data.HexString
|
import Data.HexString
|
||||||
import Data.Int
|
import Data.Int
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
@ -135,6 +136,29 @@ data TransparentBundle = TransparentBundle
|
||||||
, tb_coinbase :: !Bool
|
, tb_coinbase :: !Bool
|
||||||
} deriving (Eq, Prelude.Show, Read)
|
} deriving (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
-- | Read a raw transparent bundle into the Haskell type
|
||||||
|
fromRawTBundle :: RawTBundle -> Maybe TransparentBundle
|
||||||
|
fromRawTBundle rtb =
|
||||||
|
if ztb_empty rtb
|
||||||
|
then Nothing
|
||||||
|
else Just $
|
||||||
|
TransparentBundle
|
||||||
|
(map fromRawTxIn $ ztb_vin rtb)
|
||||||
|
(map fromRawTxOut $ ztb_vout rtb)
|
||||||
|
(ztb_coinbase rtb)
|
||||||
|
|
||||||
|
fromRawTxIn :: RawTxIn -> H.TxIn
|
||||||
|
fromRawTxIn t =
|
||||||
|
H.TxIn
|
||||||
|
(H.OutPoint
|
||||||
|
(read $ US.toString $ C.fromStrict $ rop_hash $ rti_outpoint t)
|
||||||
|
(rop_n $ rti_outpoint t))
|
||||||
|
(rti_script t)
|
||||||
|
(rti_seq t)
|
||||||
|
|
||||||
|
fromRawTxOut :: RawTxOut -> H.TxOut
|
||||||
|
fromRawTxOut t = H.TxOut (rto_amt t) (rto_script t)
|
||||||
|
|
||||||
-- *** Constants for Sapling Human-readable part
|
-- *** Constants for Sapling Human-readable part
|
||||||
sapExtSpendingKeyHrp = "secret-extended-key-main" :: String
|
sapExtSpendingKeyHrp = "secret-extended-key-main" :: String
|
||||||
|
|
||||||
|
@ -262,7 +286,8 @@ data RawZebraTx = RawZebraTx
|
||||||
|
|
||||||
-- | Type for a raw deserialized Zebra transparent bundle
|
-- | Type for a raw deserialized Zebra transparent bundle
|
||||||
data RawTBundle = RawTBundle
|
data RawTBundle = RawTBundle
|
||||||
{ ztb_vin :: ![RawTxIn]
|
{ ztb_empty :: !Bool
|
||||||
|
, ztb_vin :: ![RawTxIn]
|
||||||
, ztb_vout :: ![RawTxOut]
|
, ztb_vout :: ![RawTxOut]
|
||||||
, ztb_coinbase :: !Bool
|
, ztb_coinbase :: !Bool
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
|
@ -323,7 +348,7 @@ data TransparentAddress = TransparentAddress
|
||||||
|
|
||||||
-- | Wrapper types for transparent elements
|
-- | Wrapper types for transparent elements
|
||||||
data RawTxIn = RawTxIn
|
data RawTxIn = RawTxIn
|
||||||
{ rti_outpoint :: !Word32
|
{ rti_outpoint :: !RawOutPoint
|
||||||
, rti_script :: !BS.ByteString
|
, rti_script :: !BS.ByteString
|
||||||
, rti_seq :: !Word32
|
, rti_seq :: !Word32
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
|
@ -339,6 +364,14 @@ data RawTxOut = RawTxOut
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawTxOut
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawTxOut
|
||||||
|
|
||||||
|
data RawOutPoint = RawOutPoint
|
||||||
|
{ rop_hash :: !BS.ByteString
|
||||||
|
, rop_n :: !Word32
|
||||||
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct RawOutPoint
|
||||||
|
|
||||||
-- * Sapling
|
-- * Sapling
|
||||||
-- | A spending key for Sapling
|
-- | A spending key for Sapling
|
||||||
newtype SaplingSpendingKey =
|
newtype SaplingSpendingKey =
|
||||||
|
|
|
@ -58,6 +58,7 @@ library
|
||||||
, text
|
, text
|
||||||
, haskoin-core
|
, haskoin-core
|
||||||
, secp256k1-haskell
|
, secp256k1-haskell
|
||||||
|
, utf8-string
|
||||||
build-tool-depends:
|
build-tool-depends:
|
||||||
c2hs:c2hs
|
c2hs:c2hs
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
Loading…
Reference in a new issue