feat(rpc): implement shieldnotes method

This commit is contained in:
Rene Vergara 2024-12-18 13:31:13 -06:00
parent b88e32f701
commit 9546613e0f
Signed by: pitmutt
SSH key fingerprint: SHA256:vNa8FIqbBZjV9hOCkXyOzd7gqWCMCfkcfiPH2zaGfQ0
7 changed files with 195 additions and 106 deletions

View file

@ -780,8 +780,8 @@ listDrawTx znet sel tx =
else displayTaz amt else displayTaz amt
fmtAmt = fmtAmt =
if amt > 0 if amt > 0
then "" <> dispAmount <> " " then " " <> dispAmount <> " "
else " " <> dispAmount <> "" else " " <> dispAmount <> " "
selStr s = selStr s =
if sel if sel
then withAttr customAttr (txt $ "> " <> s) then withAttr customAttr (txt $ "> " <> s)

View file

@ -777,88 +777,94 @@ shieldTransparentNotes pool zHost zPort znet za bh = do
return [Left ZHError] return [Left ZHError]
Just acc -> do Just acc -> do
trNotes' <- liftIO $ getWalletUnspentTrNotes pool za trNotes' <- liftIO $ getWalletUnspentTrNotes pool za
dRecvs <- liftIO $ getReceivers pool trNotes' if null trNotes'
let fNotes = then return [Left InsufficientFunds]
map else do
(\x -> dRecvs <- liftIO $ getReceivers pool trNotes'
filter (\y -> walletTrNoteAddress (entityVal y) == x) trNotes') let fNotes =
dRecvs map
sTree <- liftIO $ getSaplingTree pool (\x ->
oTree <- liftIO $ getOrchardTree pool filter
forM fNotes $ \trNotes -> do (\y -> walletTrNoteAddress (entityVal y) == x)
opid <- liftIO nextRandom trNotes')
startTime <- liftIO getCurrentTime dRecvs
opkey <- sTree <- liftIO $ getSaplingTree pool
liftIO $ oTree <- liftIO $ getOrchardTree pool
saveOperation pool $ forM fNotes $ \trNotes -> do
Operation (ZenithUuid opid) startTime Nothing Processing Nothing opid <- liftIO nextRandom
case opkey of startTime <- liftIO getCurrentTime
Nothing -> return $ Left ZHError opkey <-
Just opkey' -> do
let noteTotal = getTotalAmount (trNotes, [], [])
tSpends <-
liftIO $ liftIO $
prepTSpends saveOperation pool $
(getTranSK $ zcashAccountTPrivateKey $ entityVal acc) Operation (ZenithUuid opid) startTime Nothing Processing Nothing
trNotes case opkey of
chgAddr <- getInternalAddresses pool $ entityKey acc Nothing -> return $ Left ZHError
let internalUA = Just opkey' -> do
getUA $ walletAddressUAddress $ entityVal $ head chgAddr let noteTotal = getTotalAmount (trNotes, [], [])
let oRcvr = tSpends <-
fromJust $
o_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
let dummy =
OutgoingNote
4
(getBytes $
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
(getBytes oRcvr)
(fromIntegral $ noteTotal - 500)
""
True
let feeAmt = calculateTxFee (trNotes, [], []) [dummy]
let snote =
OutgoingNote
4
(getBytes $
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
(getBytes oRcvr)
(fromIntegral $ noteTotal - fromIntegral feeAmt)
""
True
_ <-
liftIO $
forkIO $ do
tx <-
liftIO $ liftIO $
createTransaction prepTSpends
(maybe (hexString "00") (getHash . value . fst) sTree) (getTranSK $ zcashAccountTPrivateKey $ entityVal acc)
(maybe (hexString "00") (getHash . value . fst) oTree) trNotes
tSpends chgAddr <- getInternalAddresses pool $ entityKey acc
[] let internalUA =
[] getUA $ walletAddressUAddress $ entityVal $ head chgAddr
[snote] let oRcvr =
znet fromJust $
(bh + 3) o_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
True let dummy =
case tx of OutgoingNote
Left e -> 4
finalizeOperation pool opkey' Failed $ T.pack $ show e (getBytes $
Right rawTx -> do getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
zebraRes <- (getBytes oRcvr)
makeZebraCall (fromIntegral $ noteTotal - 500)
zHost ""
zPort True
"sendrawtransaction" let feeAmt = calculateTxFee (trNotes, [], []) [dummy]
[Data.Aeson.String $ toText rawTx] let snote =
case zebraRes of OutgoingNote
Left e1 -> 4
finalizeOperation pool opkey' Failed $ T.pack $ show e1 (getBytes $
Right txId -> getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
finalizeOperation pool opkey' Successful $ (getBytes oRcvr)
"Tx ID: " <> toText txId (fromIntegral $ noteTotal - fromIntegral feeAmt)
logDebugN $ T.pack $ show opid ""
return $ Right opid True
_ <-
liftIO $
forkIO $ do
tx <-
liftIO $
createTransaction
(maybe (hexString "00") (getHash . value . fst) sTree)
(maybe (hexString "00") (getHash . value . fst) oTree)
tSpends
[]
[]
[snote]
znet
(bh + 3)
True
case tx of
Left e ->
finalizeOperation pool opkey' Failed $ T.pack $ show e
Right rawTx -> do
zebraRes <-
makeZebraCall
zHost
zPort
"sendrawtransaction"
[Data.Aeson.String $ toText rawTx]
case zebraRes of
Left e1 ->
finalizeOperation pool opkey' Failed $
T.pack $ show e1
Right txId ->
finalizeOperation pool opkey' Successful $
"Tx ID: " <> toText txId
logDebugN $ T.pack $ show opid
return $ Right opid
where where
getTotalAmount :: getTotalAmount ::
( [Entity WalletTrNote] ( [Entity WalletTrNote]

View file

@ -307,11 +307,8 @@ instance FromJSON ZenithResponse where
pure $ NoteListResponse i k5 pure $ NoteListResponse i k5
Nothing -> fail "Unknown object" Nothing -> fail "Unknown object"
String s -> do String s -> do
case U.fromText s of k7 <- parseJSON r1
Nothing -> fail "Unknown value" pure $ MultiOpResponse i k7
Just _u -> do
k7 <- parseJSON r1
pure $ MultiOpResponse i k7
_anyOther -> fail "Malformed JSON" _anyOther -> fail "Malformed JSON"
Number k -> do Number k -> do
case floatingOrInteger k of case floatingOrInteger k of
@ -611,7 +608,7 @@ zenithServer state = getinfo :<|> handleRPC
return $ return $
InfoResponse InfoResponse
(callId req) (callId req)
(ZenithInfo "0.7.0.0-beta" (w_network state) (w_build state)) (ZenithInfo "0.8.0.0-beta" (w_network state) (w_build state))
_anyOtherParams -> _anyOtherParams ->
return $ ErrorResponse (callId req) (-32602) "Invalid params" return $ ErrorResponse (callId req) (-32602) "Invalid params"
ListReceived -> ListReceived ->

View file

@ -86,7 +86,7 @@ main = do
Left e -> assertFailure e Left e -> assertFailure e
Right r -> Right r ->
r `shouldBe` r `shouldBe`
InfoResponse "zh" (ZenithInfo "0.7.0.0-beta" TestNet "v1.9.0") InfoResponse "zh" (ZenithInfo "0.8.0.0-beta" TestNet "v2.1.0")
describe "Wallets" $ do describe "Wallets" $ do
describe "listwallet" $ do describe "listwallet" $ do
it "bad credentials" $ do it "bad credentials" $ do
@ -676,6 +676,54 @@ main = do
case res of case res of
Left e -> assertFailure e Left e -> assertFailure e
Right (SendResponse i o) -> o `shouldNotBe` U.nil Right (SendResponse i o) -> o `shouldNotBe` U.nil
describe "Shield notes" $ do
it "bad credentials" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
"baduser"
"idontknow"
ShieldNotes
BlankParams
res `shouldBe` Left "Invalid credentials"
describe "correct credentials" $ do
it "no parameters" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ShieldNotes
BlankParams
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32602)
it "invalid account" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ShieldNotes
(ShieldNotesParams 27)
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32006)
it "valid account" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ShieldNotes
(ShieldNotesParams 1)
case res of
Left e -> assertFailure e
Right (MultiOpResponse i c) -> c `shouldNotBe` []
startAPI :: Config -> IO () startAPI :: Config -> IO ()
startAPI config = do startAPI config = do

View file

@ -643,8 +643,7 @@ main = do
case ix of case ix of
Nothing -> assertFailure "couldn't find index at block" Nothing -> assertFailure "couldn't find index at block"
Just i -> do Just i -> do
updatedTree <- updatedTree <- runNoLoggingT $ truncateTree oTree i
runFileLoggingT "test.log" $ truncateTree oTree i
let finalAnchor = let finalAnchor =
getOrchardTreeAnchor $ getOrchardTreeAnchor $
OrchardCommitmentTree $ ztiOrchard zebraTreesIn OrchardCommitmentTree $ ztiOrchard zebraTreesIn
@ -737,7 +736,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -763,7 +762,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -787,7 +786,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -815,7 +814,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -847,7 +846,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -873,7 +872,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -897,7 +896,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -926,7 +925,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -957,7 +956,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -983,7 +982,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1007,7 +1006,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1034,7 +1033,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1061,7 +1060,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1086,7 +1085,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runFileLoggingT "zenith.log" $ runNoLoggingT $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"

@ -1 +1 @@
Subproject commit 4289a9ded67ef2ca432abc412934fb5b8b59a9cf Subproject commit d350c2e7844a526ff9b21bb14e1723fce9b0b46b

View file

@ -686,6 +686,45 @@
"items": { "$ref": "#/components/contentDescriptors/OperationId"} "items": { "$ref": "#/components/contentDescriptors/OperationId"}
} }
}, },
"examples": [
{
"name": "Shield transparent notes",
"summary": "Shield transparent notes",
"description": "Shield the transparent notes in a given account",
"params": [
{
"name": "Account index",
"summary": "The index for the account to use",
"value": "3"
}
],
"result": {
"name": "ShieldNotes result",
"value": [
"ab350df0-9f57-44c0-9e0d-f7b8af1f4231",
"8c6f2656-22ef-4f9d-b465-80ddd13fc485"
]
}
},
{
"name": "No transparent funds",
"summary": "Shield transparent notes with no transparent funds",
"description": "Attempt to shield the transparent notes in a given account, when account has none",
"params": [
{
"name": "Account index",
"summary": "The index for the account to use",
"value": "3"
}
],
"result": {
"name": "ShieldNotes result",
"value": [
"InsufficientFunds"
]
}
}
],
"errors": [ "errors": [
{ "$ref": "#/components/errors/ZebraNotAvailable" }, { "$ref": "#/components/errors/ZebraNotAvailable" },
{ "$ref": "#/components/errors/ZenithBusy" }, { "$ref": "#/components/errors/ZenithBusy" },