Some notes about Transaction publishing, normalization, verification, and broadcast on ADM node #46
adamant-al
started this conversation in
Developers & API
Replies: 1 comment
-
|
Further reading
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Functions
Transaction.prototype.verify— checks a transaction retrieved from other blocks; may include old transactions.Transactions.prototype.publish— checks incoming transactions from users, verifying "fresh" unconfirmed transactions.verifyis also called after receiving a new transaction from the API, following thepublishandobjectNormalizemethods.publishis only called when pushing transactions via the public API.Transaction processing
Receiving a new tx from a client app via API (it's the first node that sees the tx):
Logic->Transaction.prototype.publishcreates a new transaction from the received data, validates the client's transaction properties (includingtimestampMs), and adds a transaction ID.Receiving a new tx from another peer at the current height:
Fetching a tx from another peer when arising/verifying the blockchain from height 0:
Validating transaction:
objectNormalize()for schema validation of a received transaction.Processing an unconfirmed transaction flow:
logic.transaction.process()is called. It verifies the transaction ID and normalizes the sender ID.logic.transaction.objectNormalize()method validates the transaction object against a schema and removes unnecessary properties, includingtimestampMsbefore spaceship activation.logic.transaction.verify()is called, verifying all properties such astimestamp,timestampMs,signature, etc.Notes and Q/A:
BANNEDstatus is never applied).objectNormalize(), node hasnormalize(). Thenormalize()method is only used for POST/transactions/normalizeendpoint that should be deprecated.apply()andapplyUnconfirmed()? "apply" methods change balances of the sender and recipient accounts.applyUnconfirmed()changes unconfirmed balance. Same goes for "undo" methods.publish():Transaction timestamp is in the futureTransaction timestamp is more than ${constants.maxTransactionAgeSec} seconds in the pastpublishmethod as inverifybecause the latter MUST be called afterpublish. Also, we can't includepublish's checks in theverifymethod because they depend on the current time. It's impossible to verify whether an old transaction is no more than 5 seconds old.The difference between timestamp and timestampMs is greater than ${maxTimestampMsDelta}ms.orInvalid transaction timestamp. Timestamp is not in the int32 rangeif it's not inpublish()but inverify()? Yes.Timestamp notes
timestampis ADAMANT epoch time in seconds, not Unix time.timestampMsshould be ADAMANT epoch time in milliseconds, not Unix time. Unix milliseconds can be derived asconstants.epochTime.getTime() + timestampMs.timestampMsis not part of transaction bytes, signatures, transaction IDs, or hashes, including after thespaceshipactivation.spaceship, consensus-sensitive validation should requiretimestampMsto be in the same ADAMANT epoch second astimestamp:0 <= timestampMs - timestamp * 1000 < 1000.timestampMsmust refine the exact same ADAMANT epoch second stored intimestamp; clients should computetimestamp = Math.floor(timestampMs / 1000). UsingMath.round()orMath.ceil()near a second boundary creates an inconsistent pair and should be rejected.adamant-api-jsclientusesgetEpochTime()withMath.floor; PWA usesadamant.epochTime()/transaction signing withMath.floor;adamant-consoledelegates transaction creation toadamant-api@2.4.0, whosegetEpochTime()also usesMath.floor; iOS builds outgoingNormalizedTransaction.timestampby converting the positive ADAMANT epoch interval toUInt64, which truncates fractional seconds and is equivalent to floor for current transactions; docs examples useMath.floor; schema contains no client-side timestamp generation logic. No outgoing ADM transaction timestamp generation path usingroundorceilwas found.spaceship, consensus-sensitive normalization should removetimestampMsso pre-activation behavior stays compatible with older nodes.timestampMshelps clients sort fast chat messages but must not become a transaction nonce or signature input.Admission-time checks
publish()contains public API admission checks for freshly submitted transactions. These checks may depend on the node's current clock.publish(), it is still processed byverify().verify()intentionally has no current-time check and should keep only deterministic checks: schema, id, signatures, balances, and thetimestampMssame-second rule.publish()must not be moved intoverify()becauseverify()is used for replay, synchronization, and historical transactions.Transaction timestamp is in the futurewhen the rounded seconds timestamp crosses into the next slot.maxTransactionFutureMsis a non-consensus public API admission tolerance. It should be applied only inpublish(), not in replay, peer/block verification, or consensus activation logic.transactionSlotNumber > currentSlotNumberand the transaction time is more thanmaxTransactionFutureMsahead of the node's current time.timestampMswhen the client provided it; otherwise fall back totimestamp * 1000.publish()(for example, 500 ms for the next slot) can improve UX for slightly fast client clocks without changing replay validation. Client apps should still keep a small timestamp reserve for compatibility with older nodes.timestampis one second ahead of the current block can still be included in that block. This does not break the blockchain: transactiontimestampis signed transaction metadata, not the source of slot or block validity, and consensus does not requiretx.timestamp <= block.timestamp.Status endpoint
/api/node/statusmay return additional clock fields such asnodeTimestampMs(ADAMANT epoch milliseconds) andunixTimestampMswithout consensus impact.nodeTimestampremains ADAMANT epoch seconds.Activation heights
fairSystemActivateBlock: 4359464check usedheight > fairSystemActivateBlock, so the equivalent first active height for a namedfairSystemactivation is4,359,465.spaceshipactivation should gate only consensus-sensitive behavior such as accepting, normalizing, storing, and validatingtimestampMsduring block/peer/replay processing. Clock-relativepublish()checks are admission policy and should remain outside consensus activation.Beta Was this translation helpful? Give feedback.
All reactions