js-algorand-sdk
js-algorand-sdk copied to clipboard
keyreg transactions with `voteFirst: 0` fail to send
Subject of the issue
An online key registration transaction with voteFirst: 0 fails to send to the network.
Your environment
- JS SDK version: 3.1.0
- Software version: 4.0.1.stable
Steps to reproduce
- Create a key registration transaction with
voteFirst: 0. The transaction is created without any issues.
const suggestedParams = await algod.getTransactionParams().do()
const sender = localnet.context.testAccount
const txn = new algosdk.Transaction({
type: algosdk.TransactionType.keyreg,
sender: sender.addr,
keyregParams: {
voteKey: algosdk.base64ToBytes('5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE='),
selectionKey: algosdk.base64ToBytes('oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4='),
stateProofKey: algosdk.base64ToBytes('mgh7ddGf7dF1Z5/9RDzN/JZZF9yA7XYCKJXvqhwPdvI7pLKh7hizaM5rTC2kizVOpVRIU9PXSLeapvBJ/OxQYA=='),
voteFirst: 0,
voteLast: 61,
voteKeyDilution: 1234,
},
suggestedParams,
})
const signedTxn = algosdk.signTransaction(txn, sender.sk)
- Send the transaction
const res = await algod.sendRawTransaction(signedTxn.blob).do()
Expected behaviour
The transaction is successfully sent.
Actual behaviour
An exception with message "Online key registration missing at least one of the following fields: voteKey, selectionKey, voteFirst, voteLast, voteKeyDilution" is thrown when sending
Additionally, the same error is thrown when fetching a block containing a keyreg transaction sent (via another mechanism) with voteFirst: 0.
For example:
// round 66 contains a keyreg sent with `voteFirst: 0`
const res = await algod.block(66).do()
voteFirst == 0 doesn't really make sense, since it's supposed to be a round in which the given key can vote. But 0 is not an actual round. (Even if you call the genesis round 0, there's no voting there.)
However, the protocol does not require voteFirst to not be 0, so at the very least, I agree the sdk should decode such transactions. Do we really want to stop erroring on trying to send them though? It seems like this is likely to catch more problems than it causes, since 0 is never needed to send.
@nullun What's the scenario you had for sending a voteFirst: 0?
I encounted this specifically when working with a local network, running tests, and trying to view the results on Lora.
I started a fresh network and immediately generated a partkey for a genesis funded account using goal.
My test (and network) would last less than 1000 rounds, so the partkey had a --roundFirstValid of 0, with a --roundLastValid of 1000, and I submitted keyreg for it.
I'm aware I could set the roundFirstValid to 1, but 0 is still a valid transaction and as a result Lora fails to parse the transaction or process blocks which come after it. I don't think you could submit such a transaction on Mainnet or Testnet now, but things like Fnet and other local environments with lower round numbers would still potentially hiccup on this.
So we want Lora (through the sdk) to be able to read such a transaction, but I'm not hearing enthusiasm for sending such transactions. (Of course, I'd argue for simplicity, so if it's easier to support both because it's a single code path, I'd be ok with that.)
That sounds reasonable. I agree it probably shouldn't be encouraged to create a transaction with the first valid round set to 0, but in the event a transaction like that appears, the SDK should be able to handle it.