Compare commits

..

3 commits

Author SHA1 Message Date
f593fefd7f
Add types for low-level transparent components 2024-03-26 15:37:04 -05:00
ee27860299
Merge branch 'dev040' into rav001 2024-03-26 09:56:38 -05:00
4e86a2f5a4
Zebra Raw Tx deserialization (#44)
Implements features to deserialize the hex representation of of a Zebra Transaction

Reviewed-on: #44
Co-authored-by: Rene Vergara <rene@vergara.network>
Co-committed-by: Rene Vergara <rene@vergara.network>
2024-03-26 14:56:10 +00:00
3 changed files with 72 additions and 8 deletions

View file

@ -36,6 +36,7 @@ use zcash_primitives::{
Bundle as TransparentBundle,
TxIn,
TxOut,
OutPoint,
Authorized
},
sapling::{
@ -246,6 +247,7 @@ impl<RW> ToHaskell<RW> for Htx {
#[derive(BorshSerialize, BorshDeserialize)]
pub struct HTBundle {
empty: bool,
vin: Vec<HTxIn>,
vout: Vec<HTxOut>,
coinbase: bool
@ -260,13 +262,13 @@ impl<RW> ToHaskell<RW> for HTBundle {
impl 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)]
pub struct HTxIn {
outpoint: u32,
outpoint: Houtpoint,
script: Vec<u8>,
sequence: u32
}
@ -280,7 +282,7 @@ impl<RW> ToHaskell<RW> for HTxIn {
impl 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)]
pub struct Hufvk {
net: u8,
@ -651,11 +672,20 @@ pub extern "C" fn rust_wrapper_tx_read(
let parsed_tx = Transaction::read(&mut tx_reader, Nu5);
match parsed_tx {
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);
},
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) => {
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);
}
}

View file

@ -30,6 +30,7 @@ import Data.Aeson
import qualified Data.ByteArray as BA
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C
import qualified Data.ByteString.Lazy.UTF8 as US
import Data.HexString
import Data.Int
import Data.Maybe (fromMaybe)
@ -135,6 +136,29 @@ data TransparentBundle = TransparentBundle
, tb_coinbase :: !Bool
} 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
sapExtSpendingKeyHrp = "secret-extended-key-main" :: String
@ -262,7 +286,8 @@ data RawZebraTx = RawZebraTx
-- | Type for a raw deserialized Zebra transparent bundle
data RawTBundle = RawTBundle
{ ztb_vin :: ![RawTxIn]
{ ztb_empty :: !Bool
, ztb_vin :: ![RawTxIn]
, ztb_vout :: ![RawTxOut]
, ztb_coinbase :: !Bool
} deriving stock (Eq, Prelude.Show, GHC.Generic)
@ -323,7 +348,7 @@ data TransparentAddress = TransparentAddress
-- | Wrapper types for transparent elements
data RawTxIn = RawTxIn
{ rti_outpoint :: !Word32
{ rti_outpoint :: !RawOutPoint
, rti_script :: !BS.ByteString
, rti_seq :: !Word32
} deriving stock (Eq, Prelude.Show, GHC.Generic)
@ -339,6 +364,14 @@ data RawTxOut = RawTxOut
deriving anyclass (Data.Structured.Show)
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
-- | A spending key for Sapling
newtype SaplingSpendingKey =

View file

@ -58,6 +58,7 @@ library
, text
, haskoin-core
, secp256k1-haskell
, utf8-string
build-tool-depends:
c2hs:c2hs
default-language: Haskell2010