Masternode vote transition does not validate `indexValues` value
Expected Behavior
GRPC broadcastStateTransition query throw a error and an explanation if transaction is not valid
Current Behavior
MasternodeVoteTransition's indexValues is an Vec<Value> that usually accepts a string, but if you pass a base64 for example, it does not validate the values. Such transaction successfully accepted by broadcastStateTransition method, meaning that it was accepted by the chain. However, since transaction is not fully valid, it does not get in the chain and get stucked in the mempool.
/org.dash.platform.dapi.v0.Platform/broadcastStateTransition ALREADY_EXISTS: state transition already in mempool
If I switch the ordering of indexValues, the same broadcast fails with:
/org.dash.platform.dapi.v0.Platform/broadcastStateTransition INTERNAL: Internal error
Possible Solution
Implement checks in the Drive
Steps to Reproduce (for bugs)
- Create invalid MasternodeVoteTransition
- Try to broadcast
- The error is not thrown
- Transaction is not appearing on Platform Explorer
Context
Your Environment
- Version used:
- Environment name and version (e.g. Chrome 39, node.js 5.4):
- Operating System and version (desktop, server, or mobile):
- Link to your project:
In the dapi-api container:
[05:50:40.338] ERROR (35): State Transition processing error. Please report faulty state transition and try to create a new state transition with different hash as a workaround.
err: {
"type": "Error",
"message": "State Transition processing error. Please report faulty state transition and try to create a new state transition with different hash as a workaround.",
"stack":
Error: State Transition processing error. Please report faulty state transition and try to create a new state transition with different hash as a workaround.
at broadcastStateTransitionHandler (/platform/packages/dapi/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js:122:27)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async rpcMethodErrorHandler (/platform/packages/js-grpc-common/lib/server/error/wrapInErrorHandlerFactory.js:25:24)
}
```
TX hex:
```
0800559db949f305ae7ca1f2c3fafbde707a5adcb9ef7d53f99df4600d72b6bab965a01816cad4a55e3aaa88e7d93c97dda27c7dcb850f2d6fc86066cc9ea036aa86000000e668c659af66aee1e72c186dde7b5b7e0a1d712a09c40d5721f622bf53c5315506646f6d61696e12706172656e744e616d65416e644c6162656c02120464617368120a7465733164656e74317400a821fba93b8585830b65459467a071c1c0fd159517ba0539f34016fa580a9db90100411f0769aa375ac5508a02a2a332b60959796752b9f5f93b94c29a18c98619f284db191b25113e1e121c665211d2baaec8190da645d068c2740aec5aa92bcce3ff65
```
Transaction that gets stuck in mempool on testnet - passes check_tx but is rejected in prepare proposal.
State transition in hex:
08002e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb4f434f879824eba6c700076c127c0ea2968c63c553031ad33b14d3ef848aa66a000000e668c659af66aee1e72c186dde7b5b7e0a1d712a09c40d5721f622bf53c5315506646f6d61696e12706172656e744e616d65416e644c6162656c02120464617368120a61647333666164736466021400411f226662fb56b1df95aa943c4f0345628bbba50787ed7f871e9f18915e4804e0d779d56b6ee1236639607498d41c869d9fd8389de751a7bac5c4411d92a678c94a
Tenderdash tx id: 1A8D6B02FFB57C516E435FC606E0DE460424A7BDF9083F38AD114594616008D5
Drive logs:
{"timestamp":"2025-11-14T11:11:07.075462Z","level":"TRACE","fields":{"message":"Processing MasternodeVote state transition","state_transition":"MasternodeVote(V0(MasternodeVoteTransitionV0 { pro_tx_hash: Identifier(IdentifierBytes32([46, 72, 101, 26, 46, 156, 12, 180, 242, 251, 122, 184, 116, 6, 26, 164, 175, 12, 210, 139, 89, 105, 86, 49, 230, 163, 90, 243, 149, 14, 246, 251])), voter_identity_id: Identifier(IdentifierBytes32([79, 67, 79, 135, 152, 36, 235, 166, 199, 0, 7, 108, 18, 124, 14, 162, 150, 140, 99, 197, 83, 3, 26, 211, 59, 20, 211, 239, 132, 138, 166, 106])), vote: ResourceVote(V0(ResourceVoteV0 { vote_poll: ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll { contract_id: Identifier(IdentifierBytes32([230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85])), document_type_name: \"domain\", index_name: \"parentNameAndLabel\", index_values: [Text(\"dash\"), Text(\"ads3fadsdf\")] }), resource_vote_choice: Lock })), nonce: 20, signature_public_key_id: 0, signature: BinaryData(0x1f226662fb56b1df95aa943c4f0345628bbba50787ed7f871e9f18915e4804e0d779d56b6ee1236639607498d41c869d9fd8389de751a7bac5c4411d92a678c94a)}))","st_hash":"1a8d6b02ffb57c516e435fc606e0de460424a7bdf9083f38ad114594616008d5"},"target":"drive_abci::execution::platform_events::state_transition_processing::process_raw_state_transitions::v0","span":{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"},"spans":[{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"}],"threadName":"main","threadId":"ThreadId(1)"}
{"timestamp":"2025-11-14T11:11:07.088403Z","level":"DEBUG","fields":{"message":"Invalid MasternodeVote state transition without identity (1a8d6b02ffb57c516e435fc606e0de460424a7bdf9083f38ad114594616008d5): VotePoll ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string ads3fadsdf] }) not found","error":"StateError(VotePollNotFoundError(VotePollNotFoundError { vote_poll: ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll { contract_id: Identifier(IdentifierBytes32([230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85])), document_type_name: \"domain\", index_name: \"parentNameAndLabel\", index_values: [Text(\"dash\"), Text(\"ads3fadsdf\")] }) }))","st_hash":"1a8d6b02ffb57c516e435fc606e0de460424a7bdf9083f38ad114594616008d5"},"target":"drive_abci::execution::platform_events::state_transition_processing::process_raw_state_transitions::v0","span":{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"},"spans":[{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"}],"threadName":"main","threadId":"ThreadId(1)"}
{"timestamp":"2025-11-14T11:11:07.088698Z","level":"DEBUG","fields":{"message":"No queued withdrawal documents found to pool into transactions","height":213631,"withdrawal_limit":4},"target":"drive_abci::execution::platform_events::withdrawals::pool_withdrawals_into_transactions_queue::v1","span":{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"},"spans":[{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"}],"threadName":"main","threadId":"ThreadId(1)"}
...
{"timestamp":"2025-11-14T11:11:07.096705Z","level":"TRACE","fields":{"message":"UnpaidConsensusError at height 213631, round 0: StateError(VotePollNotFoundError(VotePollNotFoundError { vote_poll: ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll { contract_id: Identifier(IdentifierBytes32([230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85])), document_type_name: \"domain\", index_name: \"parentNameAndLabel\", index_values: [Text(\"dash\"), Text(\"ads3fadsdf\")] }) }))"},"target":"drive_abci::abci::handler::prepare_proposal","span":{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"},"spans":[{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"}],"threadName":"main","threadId":"ThreadId(1)"}
{"timestamp":"2025-11-14T11:11:07.096805Z","level":"INFO","fields":{"message":"Prepared proposal with 0 transition for height: 213631, round: 0 in 23 ms","invalid_paid_tx_count":0,"invalid_unpaid_tx_count":1,"valid_tx_count":0,"delayed_tx_count":0,"failed_tx_count":0,"storage_fees":0,"processing_fees":0},"target":"drive_abci::abci::handler::prepare_proposal","span":{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"},"spans":[{"endpoint":"PrepareProposal","height":213631,"request_id":"d2cf8c71-4471-4404-a381-c7cefa9e8faf","round":0,"name":"abci"}],"threadName":"main","threadId":"ThreadId(1)"}
So the tx was removed from block despite passing earlier check_tx.