Repository: zcash/zcash (language: rust)

Issue:
getblocksubsidy with v5.6.0 does not work as expected
<!--
This issue tracker is only for technical issues related to zcashd.

General Zcash questions and/or support requests and are best directed to the
Zcash Forum: https://forum.zcashcommunity.com/

For reporting security vulnerabilities or for sensitive discussions with our
security team, please email security@z.cash . You can use this GPG key to send
an encrypted message:
    https://z.cash/gpg-pubkeys/security.asc
    fingerprint: AF85 0445 546C 18B7 86F9  2C62 88FB 8B86 D8B5 A68C

The key and fingerprint are duplicated on our Public Keys page:
https://z.cash/support/pubkeys.html
-->

### Describe the issue
In the new version of zcash v5.6.0 when I call getblocksubsidy without params, get error:
`{"result":null,"error":{"code":-32602,"message":"Not enough parameters for method `getblocksubsidy`. Needed exactly 1, but received 0\n\ngetblocksubsidy height...`

before this version that was work as expected, return:
```{"result":{"fundingstreams":[{"recipient":"Electric Coin Company","specification":"https://zips.z.cash/zip-0214","value":0.21875000,"valueZat":21875000,"address":"t3dN8g9zi2UGJdixGe9txeSxeofLS9t3yFQ"},{"recipient":"Zcash Foundation","specification":"https://zips.z.cash/zip-0214","value":0.15625000,"valueZat":15625000,"address":"t3dvVE3SQEi7kqNzwrfNePxZ1d4hUyztBA1"},{"recipient":"Major Grants","specification":"https://zips.z.cash/zip-0214","value":0.25000000,"valueZat":25000000,"address":"t3XyYW8yBFRuMnfvm5KLGFbEVz25kckZXym"}],"miner":2.50000000,"founders":0.00000000},"error":null,"id":"curltest"}```

so, I suspect, that in new version you broke some how rule:
"Arguments:
1. height         (numeric, optional) The block height.  If not provided, defaults to the current height of the chain."

### Can you reliably reproduce the issue?
#### If so, please list the steps to reproduce below:
curl --user <user> --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblocksubsidy", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:8232/

### Expected behavior
 If not provided the block height, defaults to the current height of the chain.
curl --user <user> --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblocksubsidy", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:8232/

```{"result":{"fundingstreams":[{"recipient":"Electric Coin Company","specification":"https://zips.z.cash/zip-0214","value":0.21875000,"valueZat":21875000,"address":"t3dN8g9zi2UGJdixGe9txeSxeofLS9t3yFQ"},{"recipient":"Zcash Foundation","specification":"https://zips.z.cash/zip-0214","value":0.15625000,"valueZat":15625000,"address":"t3dvVE3SQEi7kqNzwrfNePxZ1d4hUyztBA1"},{"recipient":"Major Grants","specification":"https://zips.z.cash/zip-0214","value":0.25000000,"valueZat":25000000,"address":"t3XyYW8yBFRuMnfvm5KLGFbEVz25kckZXym"}],"miner":2.50000000,"founders":0.00000000},"error":null,"id":"curltest"}```


### The version of Zcash you were using:
v.5.6.0



Discussion / hints:

Fix patch:
diff --git a/src/rpc/common.h b/src/rpc/common.h
index 29e114f280b..b4278b52db6 100644
--- a/src/rpc/common.h
+++ b/src/rpc/common.h
@@ -76,7 +76,7 @@ static const CRPCConvertTable rpcCvtTable =
     // NB: The second argument _should_ be an object, but upstream treats it as a string, so we
     //     preserve that here.
     { "submitblock",                 {{s}, {s}} },
-    { "getblocksubsidy",             {{o}, {}} },
+    { "getblocksubsidy",             {{}, {o}} },
     // misc
     { "getinfo",                     {{}, {}} },
     { "validateaddress",             {{s}, {}} },


Test patch:
diff --git a/qa/rpc-tests/nuparams.py b/qa/rpc-tests/nuparams.py
index a91b304830e..593ef63ba92 100755
--- a/qa/rpc-tests/nuparams.py
+++ b/qa/rpc-tests/nuparams.py
@@ -16,6 +16,7 @@
     CANOPY_BRANCH_ID,
     NU5_BRANCH_ID,
 )
+from decimal import Decimal
 
 
 class NuparamsTest(BitcoinTestFramework):
@@ -31,8 +32,9 @@ def __init__(self):
 
     def setup_network(self, split=False):
         args = [[
-            nuparams(HEARTWOOD_BRANCH_ID, 3),
-            nuparams(NU5_BRANCH_ID, 5),
+            nuparams(BLOSSOM_BRANCH_ID, 3),
+            nuparams(CANOPY_BRANCH_ID, 5),
+            nuparams(NU5_BRANCH_ID, 7),
         ] * self.num_nodes]
         self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, args)
         self.is_network_split = False
@@ -62,7 +64,7 @@ def run_test(self):
 
         heartwood = upgrades[nustr(HEARTWOOD_BRANCH_ID)]
         assert_equal(heartwood['name'], 'Heartwood')
-        assert_equal(heartwood['activationheight'], 3)
+        assert_equal(heartwood['activationheight'], 5)
         assert_equal(heartwood['status'], 'pending')
 
         canopy = upgrades[nustr(CANOPY_BRANCH_ID)]
@@ -72,12 +74,15 @@ def run_test(self):
 
         nu5 = upgrades[nustr(NU5_BRANCH_ID)]
         assert_equal(nu5['name'], 'NU5')
-        assert_equal(nu5['activationheight'], 5)
+        assert_equal(nu5['activationheight'], 7)
         assert_equal(nu5['status'], 'pending')
 
+        # Initial subsidy at the genesis block is 12.5 ZEC
+        assert_equal(node.getblocksubsidy()["miner"], Decimal("12.5"))
+
+        # start_node() hardcodes Sapling and Overwinter to activate at height 1
         node.generate(1)
 
-        # start_node() hardcodes Sapling and Overwinter to activate a height 1
         bci = node.getblockchaininfo()
         assert_equal(bci['blocks'], 1)
         upgrades = bci['upgrades']
@@ -99,7 +104,7 @@ def run_test(self):
 
         heartwood = upgrades[nustr(HEARTWOOD_BRANCH_ID)]
         assert_equal(heartwood['name'], 'Heartwood')
-        assert_equal(heartwood['activationheight'], 3)
+        assert_equal(heartwood['activationheight'], 5)
         assert_equal(heartwood['status'], 'pending')
 
         canopy = upgrades[nustr(CANOPY_BRANCH_ID)]
@@ -109,12 +114,17 @@ def run_test(self):
 
         nu5 = upgrades[nustr(NU5_BRANCH_ID)]
         assert_equal(nu5['name'], 'NU5')
-        assert_equal(nu5['activationheight'], 5)
+        assert_equal(nu5['activationheight'], 7)
         assert_equal(nu5['status'], 'pending')
 
-        node.generate(1)
+        # After the genesis block the founders' reward consumes 20% of the block
+        # subsidy, so the miner subsidy is 10 ZEC
+        assert_equal(node.getblocksubsidy()["miner"], Decimal("10"))
+
+        # Activate Blossom
+        node.generate(2)
         bci = node.getblockchaininfo()
-        assert_equal(bci['blocks'], 2)
+        assert_equal(bci['blocks'], 3)
         upgrades = bci['upgrades']
 
         overwinter = upgrades[nustr(OVERWINTER_BRANCH_ID)]
@@ -130,11 +140,11 @@ def run_test(self):
         blossom = upgrades[nustr(BLOSSOM_BRANCH_ID)]
         assert_equal(blossom['name'], 'Blossom')
         assert_equal(blossom['activationheight'], 3)
-        assert_equal(blossom['status'], 'pending')
+        assert_equal(blossom['status'], 'active')
 
         heartwood = upgrades[nustr(HEARTWOOD_BRANCH_ID)]
         assert_equal(heartwood['name'], 'Heartwood')
-        assert_equal(heartwood['activationheight'], 3)
+        assert_equal(heartwood['activationheight'], 5)
         assert_equal(heartwood['status'], 'pending')
 
         canopy = upgrades[nustr(CANOPY_BRANCH_ID)]
@@ -144,12 +154,16 @@ def run_test(self):
 
         nu5 = upgrades[nustr(NU5_BRANCH_ID)]
         assert_equal(nu5['name'], 'NU5')
-        assert_equal(nu5['activationheight'], 5)
+        assert_equal(nu5['activationheight'], 7)
         assert_equal(nu5['status'], 'pending')
 
+        # Block subsidy halves at Blossom due to block time halving
+        assert_equal(node.getblocksubsidy()["miner"], Decimal("5"))
+
+        # Activate Heartwood & Canopy
         node.generate(2)
         bci = node.getblockchaininfo()
-        assert_equal(bci['blocks'], 4)
+        assert_equal(bci['blocks'], 5)
         upgrades = bci['upgrades']
 
         overwinter = upgrades[nustr(OVERWINTER_BRANCH_ID)]
@@ -169,22 +183,27 @@ def run_test(self):
 
         heartwood = upgrades[nustr(HEARTWOOD_BRANCH_ID)]
         assert_equal(heartwood['name'], 'Heartwood')
-        assert_equal(heartwood['activationheight'], 3)
+        assert_equal(heartwood['activationheight'], 5)
         assert_equal(heartwood['status'], 'active')
 
         canopy = upgrades[nustr(CANOPY_BRANCH_ID)]
         assert_equal(canopy['name'], 'Canopy')
         assert_equal(canopy['activationheight'], 5)
-        assert_equal(canopy['status'], 'pending')
+        assert_equal(canopy['status'], 'active')
 
         nu5 = upgrades[nustr(NU5_BRANCH_ID)]
         assert_equal(nu5['name'], 'NU5')
-        assert_equal(nu5['activationheight'], 5)
+        assert_equal(nu5['activationheight'], 7)
         assert_equal(nu5['status'], 'pending')
 
-        node.generate(1)
+        # The founders' reward ends at Canopy and there are no funding streams
+        # configured by default for regtest. On mainnet, the halving activated
+        # coincident with Canopy, but on regtest the two are independent.
+        assert_equal(node.getblocksubsidy()["miner"], Decimal("6.25"))
+
+        node.generate(2)
         bci = node.getblockchaininfo()
-        assert_equal(bci['blocks'], 5)
+        assert_equal(bci['blocks'], 7)
         upgrades = bci['upgrades']
 
         overwinter = upgrades[nustr(OVERWINTER_BRANCH_ID)]
@@ -204,7 +223,7 @@ def run_test(self):
 
         heartwood = upgrades[nustr(HEARTWOOD_BRANCH_ID)]
         assert_equal(heartwood['name'], 'Heartwood')
-        assert_equal(heartwood['activationheight'], 3)
+        assert_equal(heartwood['activationheight'], 5)
         assert_equal(heartwood['status'], 'active')
 
         canopy = upgrades[nustr(CANOPY_BRANCH_ID)]
@@ -214,9 +233,11 @@ def run_test(self):
 
         nu5 = upgrades[nustr(NU5_BRANCH_ID)]
         assert_equal(nu5['name'], 'NU5')
-        assert_equal(nu5['activationheight'], 5)
+        assert_equal(nu5['activationheight'], 7)
         assert_equal(nu5['status'], 'active')
 
+        # Block subsidy remains the same after NU5
+        assert_equal(node.getblocksubsidy()["miner"], Decimal("6.25"))
 
 if __name__ == '__main__':
     NuparamsTest().main()