platform icon indicating copy to clipboard operation
platform copied to clipboard

Masternode vote transition does not validate `indexValues` value

Open pshenmic opened this issue 3 months ago • 3 comments

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)

  1. Create invalid MasternodeVoteTransition
  2. Try to broadcast
  3. The error is not thrown
  4. 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:

pshenmic avatar Sep 10 '25 04:09 pshenmic

Image

pshenmic avatar Sep 10 '25 05:09 pshenmic

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
```

pshenmic avatar Sep 10 '25 05:09 pshenmic

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.

lklimek avatar Nov 14 '25 11:11 lklimek