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
fmtAmt =
if amt > 0
then "" <> dispAmount <> " "
else " " <> dispAmount <> ""
then " " <> dispAmount <> " "
else " " <> dispAmount <> " "
selStr s =
if sel
then withAttr customAttr (txt $ "> " <> s)

View file

@ -777,88 +777,94 @@ shieldTransparentNotes pool zHost zPort znet za bh = do
return [Left ZHError]
Just acc -> do
trNotes' <- liftIO $ getWalletUnspentTrNotes pool za
dRecvs <- liftIO $ getReceivers pool trNotes'
let fNotes =
map
(\x ->
filter (\y -> walletTrNoteAddress (entityVal y) == x) trNotes')
dRecvs
sTree <- liftIO $ getSaplingTree pool
oTree <- liftIO $ getOrchardTree pool
forM fNotes $ \trNotes -> do
opid <- liftIO nextRandom
startTime <- liftIO getCurrentTime
opkey <-
liftIO $
saveOperation pool $
Operation (ZenithUuid opid) startTime Nothing Processing Nothing
case opkey of
Nothing -> return $ Left ZHError
Just opkey' -> do
let noteTotal = getTotalAmount (trNotes, [], [])
tSpends <-
if null trNotes'
then return [Left InsufficientFunds]
else do
dRecvs <- liftIO $ getReceivers pool trNotes'
let fNotes =
map
(\x ->
filter
(\y -> walletTrNoteAddress (entityVal y) == x)
trNotes')
dRecvs
sTree <- liftIO $ getSaplingTree pool
oTree <- liftIO $ getOrchardTree pool
forM fNotes $ \trNotes -> do
opid <- liftIO nextRandom
startTime <- liftIO getCurrentTime
opkey <-
liftIO $
prepTSpends
(getTranSK $ zcashAccountTPrivateKey $ entityVal acc)
trNotes
chgAddr <- getInternalAddresses pool $ entityKey acc
let internalUA =
getUA $ walletAddressUAddress $ entityVal $ head chgAddr
let oRcvr =
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 <-
saveOperation pool $
Operation (ZenithUuid opid) startTime Nothing Processing Nothing
case opkey of
Nothing -> return $ Left ZHError
Just opkey' -> do
let noteTotal = getTotalAmount (trNotes, [], [])
tSpends <-
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
prepTSpends
(getTranSK $ zcashAccountTPrivateKey $ entityVal acc)
trNotes
chgAddr <- getInternalAddresses pool $ entityKey acc
let internalUA =
getUA $ walletAddressUAddress $ entityVal $ head chgAddr
let oRcvr =
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 $
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
getTotalAmount ::
( [Entity WalletTrNote]

View file

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

View file

@ -86,7 +86,7 @@ main = do
Left e -> assertFailure e
Right r ->
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 "listwallet" $ do
it "bad credentials" $ do
@ -676,6 +676,54 @@ main = do
case res of
Left e -> assertFailure e
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 = do

View file

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

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

View file

@ -686,6 +686,45 @@
"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": [
{ "$ref": "#/components/errors/ZebraNotAvailable" },
{ "$ref": "#/components/errors/ZenithBusy" },