feat(rpc): implement shieldnotes
method
This commit is contained in:
parent
b88e32f701
commit
9546613e0f
7 changed files with 195 additions and 106 deletions
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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 ->
|
||||
|
|
|
@ -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
|
||||
|
|
31
test/Spec.hs
31
test/Spec.hs
|
@ -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
|
|
@ -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" },
|
||||
|
|
Loading…
Reference in a new issue