Milestone 3: RPC server, ZIP-320 #104
3 changed files with 229 additions and 139 deletions
|
@ -83,6 +83,7 @@ import Zenith.Types
|
|||
, RseedDB(..)
|
||||
, SaplingSpendingKeyDB(..)
|
||||
, ScopeDB(..)
|
||||
, TransactionType(..)
|
||||
, TransparentSpendingKeyDB(..)
|
||||
, UnifiedAddressDB(..)
|
||||
, ValidAddressAPI(..)
|
||||
|
@ -737,8 +738,9 @@ prepareTxV2 ::
|
|||
-> Int
|
||||
-> [ProposedNote]
|
||||
-> PrivacyPolicy
|
||||
-> TransactionType
|
||||
-> NoLoggingT IO (Either TxError HexString)
|
||||
prepareTxV2 pool zebraHost zebraPort zn za bh pnotes policy = do
|
||||
prepareTxV2 pool zebraHost zebraPort zn za bh pnotes policy txType = do
|
||||
accRead <- liftIO $ getAccountById pool za
|
||||
let recipients = map extractReceiver pnotes
|
||||
logDebugN $ T.pack $ show recipients
|
||||
|
@ -760,13 +762,19 @@ prepareTxV2 pool zebraHost zebraPort zn za bh pnotes policy = do
|
|||
--let fee = calculateTxFee firstPass $ fst recipient
|
||||
--logDebugN $ T.pack $ "calculated fee " ++ show fee
|
||||
notePlan <-
|
||||
liftIO $
|
||||
selectUnspentNotesV2
|
||||
pool
|
||||
za
|
||||
(zats + 10000)
|
||||
(map (\(x, _, _, _) -> x) recipients)
|
||||
policy
|
||||
case txType of
|
||||
Normal ->
|
||||
liftIO $
|
||||
selectUnspentNotesV2
|
||||
pool
|
||||
za
|
||||
(zats + 10000)
|
||||
(map (\(x, _, _, _) -> x) recipients)
|
||||
policy
|
||||
Shielding ->
|
||||
liftIO $ selectUnspentNotesV2 pool za (zats + 10000) [3] Medium
|
||||
Deshielding ->
|
||||
liftIO $ selectUnspentNotesV2 pool za (zats + 10000) [1] None
|
||||
case notePlan of
|
||||
Right (tList, sList, oList) -> do
|
||||
logDebugN "selected notes"
|
||||
|
@ -795,7 +803,7 @@ prepareTxV2 pool zebraHost zebraPort zn za bh pnotes policy = do
|
|||
--print oSpends
|
||||
dummy' <-
|
||||
liftIO $
|
||||
makeOutgoing acc recipients (noteTotal - 5000 - zats) policy
|
||||
makeOutgoing acc recipients (noteTotal - 5000 - zats) policy txType
|
||||
case dummy' of
|
||||
Left e -> return $ Left e
|
||||
Right dummy -> do
|
||||
|
@ -818,13 +826,21 @@ prepareTxV2 pool zebraHost zebraPort zn za bh pnotes policy = do
|
|||
fromIntegral
|
||||
(runGet getInt64le $ LBS.fromStrict $ toBytes fee)
|
||||
finalNotePlan <-
|
||||
liftIO $
|
||||
selectUnspentNotesV2
|
||||
pool
|
||||
za
|
||||
(zats + feeAmt)
|
||||
(map (\(x, _, _, _) -> x) recipients)
|
||||
policy
|
||||
case txType of
|
||||
Normal ->
|
||||
liftIO $
|
||||
selectUnspentNotesV2
|
||||
pool
|
||||
za
|
||||
(zats + feeAmt)
|
||||
(map (\(x, _, _, _) -> x) recipients)
|
||||
policy
|
||||
Shielding ->
|
||||
liftIO $
|
||||
selectUnspentNotesV2 pool za (zats + feeAmt) [3] Medium
|
||||
Deshielding ->
|
||||
liftIO $
|
||||
selectUnspentNotesV2 pool za (zats + feeAmt) [1] None
|
||||
case finalNotePlan of
|
||||
Right (tList1, sList1, oList1) -> do
|
||||
logDebugN $
|
||||
|
@ -855,6 +871,7 @@ prepareTxV2 pool zebraHost zebraPort zn za bh pnotes policy = do
|
|||
recipients
|
||||
(noteTotal1 - feeAmt - zats)
|
||||
policy
|
||||
txType
|
||||
logDebugN $ T.pack $ show outgoing'
|
||||
case outgoing' of
|
||||
Left e -> return $ Left e
|
||||
|
@ -931,131 +948,189 @@ prepareTxV2 pool zebraHost zebraPort zn za bh pnotes policy = do
|
|||
-> [(Int, BS.ByteString, Int, T.Text)]
|
||||
-> Integer
|
||||
-> PrivacyPolicy
|
||||
-> TransactionType
|
||||
-> IO (Either TxError [OutgoingNote])
|
||||
makeOutgoing acc recvs chg pol = do
|
||||
makeOutgoing acc recvs chg pol tt = do
|
||||
let k = map (\(x, _, _, _) -> x) recvs
|
||||
let j = map (\(_, _, x, _) -> x) recvs
|
||||
chgAddr <- runNoLoggingT $ getInternalAddresses pool $ entityKey acc
|
||||
let internalUA = getUA $ walletAddressUAddress $ entityVal $ head chgAddr
|
||||
case pol of
|
||||
Full ->
|
||||
if elem 1 k || elem 2 k || elem 5 k || elem 6 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Receiver not compatible with privacy policy"
|
||||
else if elem 3 k && elem 4 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Multiple shielded pulls not allowed for Full privacy"
|
||||
else if 3 `elem` k
|
||||
then do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
s_rec =<<
|
||||
isValidUnifiedAddress
|
||||
(E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
3
|
||||
(getBytes $
|
||||
getSapSK $
|
||||
zcashAccountSapSpendKey $ entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes =
|
||||
map
|
||||
(prepareOutgoingNote (entityVal acc))
|
||||
recvs
|
||||
return $ Right $ cnote : onotes
|
||||
else if 4 `elem` k
|
||||
then do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
o_rec =<<
|
||||
isValidUnifiedAddress
|
||||
(E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
4
|
||||
(getBytes $
|
||||
getOrchSK $
|
||||
zcashAccountOrchSpendKey $
|
||||
entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes =
|
||||
map
|
||||
(prepareOutgoingNote (entityVal acc))
|
||||
recvs
|
||||
return $ Right $ cnote : onotes
|
||||
else return $ Left ZHError
|
||||
Medium ->
|
||||
if elem 1 k || elem 2 k || elem 5 k || elem 6 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Receiver not compatible with privacy policy"
|
||||
else do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
o_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
4
|
||||
(getBytes $
|
||||
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes = map (prepareOutgoingNote (entityVal acc)) recvs
|
||||
return $ Right $ cnote : onotes
|
||||
Low ->
|
||||
if elem 5 k || elem 6 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Receiver not compatible with privacy policy"
|
||||
else do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
o_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
4
|
||||
(getBytes $
|
||||
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes = map (prepareOutgoingNote (entityVal acc)) recvs
|
||||
return $ Right $ cnote : onotes
|
||||
None ->
|
||||
if elem 3 k || elem 4 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Receiver not compatible with privacy policy"
|
||||
else do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
t_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
1
|
||||
BS.empty
|
||||
(toBytes $ tr_bytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes = map (prepareOutgoingNote (entityVal acc)) recvs
|
||||
return $ Right $ cnote : onotes
|
||||
case tt of
|
||||
Deshielding -> do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
o_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let trRcvr =
|
||||
fromJust $
|
||||
t_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
4
|
||||
(getBytes $
|
||||
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let tnote =
|
||||
OutgoingNote
|
||||
1
|
||||
BS.empty
|
||||
(toBytes $ tr_bytes trRcvr)
|
||||
(fromIntegral $ head j)
|
||||
""
|
||||
True
|
||||
return $ Right [cnote, tnote]
|
||||
Shielding -> do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
t_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let oRcvr =
|
||||
fromJust $
|
||||
o_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
1
|
||||
BS.empty
|
||||
(toBytes $ tr_bytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let snote =
|
||||
OutgoingNote
|
||||
4
|
||||
(getBytes $
|
||||
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
||||
(getBytes oRcvr)
|
||||
(fromIntegral $ head j)
|
||||
""
|
||||
True
|
||||
return $ Right [cnote, snote]
|
||||
Normal ->
|
||||
case pol of
|
||||
Full ->
|
||||
if elem 1 k || elem 2 k || elem 5 k || elem 6 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Receiver not compatible with privacy policy"
|
||||
else if elem 3 k && elem 4 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Multiple shielded pulls not allowed for Full privacy"
|
||||
else if 3 `elem` k
|
||||
then do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
s_rec =<<
|
||||
isValidUnifiedAddress
|
||||
(E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
3
|
||||
(getBytes $
|
||||
getSapSK $
|
||||
zcashAccountSapSpendKey $ entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes =
|
||||
map
|
||||
(prepareOutgoingNote (entityVal acc))
|
||||
recvs
|
||||
return $ Right $ cnote : onotes
|
||||
else if 4 `elem` k
|
||||
then do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
o_rec =<<
|
||||
isValidUnifiedAddress
|
||||
(E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
4
|
||||
(getBytes $
|
||||
getOrchSK $
|
||||
zcashAccountOrchSpendKey $
|
||||
entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes =
|
||||
map
|
||||
(prepareOutgoingNote
|
||||
(entityVal acc))
|
||||
recvs
|
||||
return $ Right $ cnote : onotes
|
||||
else return $ Left ZHError
|
||||
Medium ->
|
||||
if elem 1 k || elem 2 k || elem 5 k || elem 6 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Receiver not compatible with privacy policy"
|
||||
else do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
o_rec =<<
|
||||
isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
4
|
||||
(getBytes $
|
||||
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes = map (prepareOutgoingNote (entityVal acc)) recvs
|
||||
return $ Right $ cnote : onotes
|
||||
Low ->
|
||||
if elem 5 k || elem 6 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Receiver not compatible with privacy policy"
|
||||
else do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
o_rec =<<
|
||||
isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
4
|
||||
(getBytes $
|
||||
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
||||
(getBytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes = map (prepareOutgoingNote (entityVal acc)) recvs
|
||||
return $ Right $ cnote : onotes
|
||||
None ->
|
||||
if elem 3 k || elem 4 k
|
||||
then return $
|
||||
Left $
|
||||
PrivacyPolicyError
|
||||
"Receiver not compatible with privacy policy"
|
||||
else do
|
||||
let chgRcvr =
|
||||
fromJust $
|
||||
t_rec =<<
|
||||
isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||
let cnote =
|
||||
OutgoingNote
|
||||
1
|
||||
BS.empty
|
||||
(toBytes $ tr_bytes chgRcvr)
|
||||
(fromIntegral chg)
|
||||
""
|
||||
True
|
||||
let onotes = map (prepareOutgoingNote (entityVal acc)) recvs
|
||||
return $ Right $ cnote : onotes
|
||||
getTotalAmount ::
|
||||
( [Entity WalletTrNote]
|
||||
, [Entity WalletSapNote]
|
||||
|
|
|
@ -1106,6 +1106,7 @@ handleEvent wenv node model evt =
|
|||
(model ^. sendRecipient)
|
||||
(model ^. sendMemo)
|
||||
(model ^. privacyChoice)
|
||||
Normal
|
||||
, Event CancelSend
|
||||
]
|
||||
CancelSend ->
|
||||
|
@ -1559,9 +1560,10 @@ sendTransaction ::
|
|||
-> T.Text
|
||||
-> T.Text
|
||||
-> PrivacyPolicy
|
||||
-> TransactionType
|
||||
-> (AppEvent -> IO ())
|
||||
-> IO ()
|
||||
sendTransaction config znet accId bl amt ua memo policy sendMsg = do
|
||||
sendTransaction config znet accId bl amt ua memo policy txType sendMsg = do
|
||||
sendMsg $ ShowModal "Preparing transaction..."
|
||||
case parseAddress (E.encodeUtf8 ua) of
|
||||
Nothing -> sendMsg $ ShowError "Incorrect address"
|
||||
|
@ -1579,8 +1581,15 @@ sendTransaction config znet accId bl amt ua memo policy sendMsg = do
|
|||
znet
|
||||
accId
|
||||
bl
|
||||
[ProposedNote (ValidAddressAPI addr) amt (Just memo)]
|
||||
[ ProposedNote
|
||||
(ValidAddressAPI addr)
|
||||
amt
|
||||
(if memo == ""
|
||||
then Nothing
|
||||
else Just memo)
|
||||
]
|
||||
policy
|
||||
txType
|
||||
case res of
|
||||
Left e -> sendMsg $ ShowError $ T.pack $ show e
|
||||
Right rawTx -> do
|
||||
|
|
|
@ -262,6 +262,12 @@ instance ToJSON ProposedNote where
|
|||
toJSON (ProposedNote a n m) =
|
||||
object ["address" .= a, "amount" .= n, "memo" .= m]
|
||||
|
||||
data TransactionType
|
||||
= Normal
|
||||
| Shielding
|
||||
| Deshielding
|
||||
deriving (Eq, Prelude.Show)
|
||||
|
||||
-- ** `zebrad`
|
||||
-- | Type for modeling the tree state response
|
||||
data ZebraTreeInfo = ZebraTreeInfo
|
||||
|
|
Loading…
Reference in a new issue