Merge pull request 'Add functionality for transaction creation' (#75) from rav001 into dev040

Reviewed-on: #75
This commit is contained in:
pitmutt 2024-05-01 14:14:40 +00:00 committed by Vergara Technologies LLC
commit 4a48769eeb
Signed by: Vergara Technologies LLC
GPG key ID: 99DB473BB4715618
4 changed files with 125 additions and 5 deletions

View file

@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.6.1.1] ## [0.6.1.1]
### Added
- Type for transaction creation errors
- Types for Sapling circuit parameters
- Function to create transaction
### Changed ### Changed
- Add `Read` instance for `Rseed` - Add `Read` instance for `Rseed`

View file

@ -1809,9 +1809,53 @@ pub extern "C" fn rust_wrapper_create_transaction(
let h = Hhex {bytes: out_bytes}; let h = Hhex {bytes: out_bytes};
marshall_to_haskell_var(&h, out, out_len, RW); marshall_to_haskell_var(&h, out, out_len, RW);
}, },
Err(_e) => { Err(e) => {
let x = Hhex {bytes: vec![0]}; match e {
marshall_to_haskell_var(&x, out, out_len, RW); Error::InsufficientFunds(_y) => {
let x = Hhex {bytes: vec![0]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::ChangeRequired(_y1) => {
let x = Hhex {bytes: vec![1]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::Fee(_y2) => {
let x = Hhex {bytes: vec![2]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::Balance(x) => {
let x = Hhex {bytes: vec![3]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::TransparentBuild(x) => {
let x = Hhex {bytes: vec![4]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::SaplingBuild(x) => {
let x = Hhex {bytes: vec![5]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::OrchardBuild(x) => {
let x = Hhex {bytes: vec![6]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::OrchardSpend(x) => {
let x = Hhex {bytes: vec![7]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::OrchardRecipient(x) => {
let x = Hhex {bytes: vec![8]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::SaplingBuilderNotAvailable => {
let x = Hhex {bytes: vec![9]};
marshall_to_haskell_var(&x, out, out_len, RW);
},
Error::OrchardBuilderNotAvailable => {
let x = Hhex {bytes: vec![10]};
marshall_to_haskell_var(&x, out, out_len, RW);
}
}
} }
} }
} }

View file

@ -692,6 +692,29 @@ data OutgoingNote = OutGoingNote
deriving anyclass (Data.Structured.Show) deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OutgoingNote deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OutgoingNote
newtype SaplingSpendParams = SaplingSpendParams
{ sapSParams :: BS.ByteString
} deriving newtype (Eq, Prelude.Show, Read)
newtype SaplingOutputParams = SaplingOutputParams
{ sapOParams :: BS.ByteString
} deriving newtype (Eq, Prelude.Show, Read)
data TxError
= InsufficientFunds
| ChangeRequired
| Fee
| Balance
| TransparentBuild
| SaplingBuild
| OrchardBuild
| OrchardSpend
| OrchardRecipient
| SaplingBuilderNotAvailable
| OrchardBuilderNotAvailable
| ZHError
deriving (Eq, Prelude.Show, Read)
-- * Classes -- * Classes
-- | Class to represent types with a bytestring representation -- | Class to represent types with a bytestring representation
class ToBytes a where class ToBytes a where

View file

@ -19,8 +19,9 @@ module ZcashHaskell.Utils where
import C.Zcash import C.Zcash
( rustWrapperBech32Decode ( rustWrapperBech32Decode
, rustWrapperBech32mEncode
, rustWrapperBech32Encode , rustWrapperBech32Encode
, rustWrapperBech32mEncode
, rustWrapperCreateTx
, rustWrapperF4Jumble , rustWrapperF4Jumble
, rustWrapperF4UnJumble , rustWrapperF4UnJumble
, rustWrapperTxRead , rustWrapperTxRead
@ -31,7 +32,7 @@ import Data.Aeson
import Data.Binary.Get import Data.Binary.Get
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy as LBS
import Data.HexString (HexString(..)) import Data.HexString (HexString(..), toBytes)
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Encoding as E import qualified Data.Text.Encoding as E
import Foreign.Rust.Marshall.Variable import Foreign.Rust.Marshall.Variable
@ -121,3 +122,49 @@ readZebraTransaction hex =
where where
rawTx = (withPureBorshVarBuffer . rustWrapperTxRead) $ hexBytes hex rawTx = (withPureBorshVarBuffer . rustWrapperTxRead) $ hexBytes hex
createTransaction ::
Maybe SaplingWitness -- ^ to obtain the Sapling anchor
-> Maybe OrchardWitness -- ^ to obtain the Orchard anchor
-> [TransparentTxSpend] -- ^ the list of transparent notes to spend
-> [SaplingTxSpend] -- ^ the list of Sapling notes to spend
-> [OrchardTxSpend] -- ^ the list of Orchard notes to spend
-> [OutgoingNote] -- ^ the list of outgoing notes, including change notes
-> SaplingSpendParams -- ^ the Sapling circuit spending parameters
-> SaplingOutputParams -- ^ the Sapling circuit output parameters
-> ZcashNet -- ^ the network to be used
-> Int -- ^ target block height
-> Either TxError HexString
createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing sParams oParams znet bh =
if BS.length (hexBytes txResult) > 1
then Right txResult
else case head (BS.unpack $ hexBytes txResult) of
0 -> Left InsufficientFunds
1 -> Left ChangeRequired
2 -> Left Fee
3 -> Left Balance
4 -> Left TransparentBuild
5 -> Left SaplingBuild
6 -> Left OrchardBuild
7 -> Left OrchardSpend
8 -> Left OrchardRecipient
9 -> Left SaplingBuilderNotAvailable
10 -> Left OrchardBuilderNotAvailable
_ -> Left ZHError
where
txResult =
withPureBorshVarBuffer $
rustWrapperCreateTx
(case sapAnchor of
Nothing -> "0"
Just sA -> toBytes $ sapWit sA)
(case orchAnchor of
Nothing -> "0"
Just oA -> toBytes $ orchWit oA)
tSpend
sSpend
oSpend
outgoing
(sapSParams sParams)
(sapOParams oParams)
(znet == MainNet)
(fromIntegral bh)