Transaction

A transaction generally represents a unit of work within a database system. In the case of blockchain, that is when an action signed by an account changes its state.

Transaction types

There are different types of transactions. For example, you can transfer mosaics between accounts, transfer or configure the ownership of accounts (including the use of multisig rules), and more.

Id Type Description
Remote harvesting    
0x414C AccountLinkTransaction Delegate the account importance to a proxy account.
Aggregate    
0x4141 AggregateCompleteTransaction Send transactions in batches to different accounts.
0x4241 AggregateBondedTransaction Propose an arrangement of transactions between different accounts.
CosignatureTransaction Cosign an AggregateBondedTransaction.
Mosaic    
0x414D MosaicDefinitionTransaction Register a new mosaic.
0x424D MosaicSupplyChangeTransaction Change an existent mosaic supply.
Namespace    
0x414E NamespaceRegistrationTransaction Register namespaces to organize your assets.
0x424E AddressAliasTransaction Attach a namespace name to an account.
0x434E MosaicAliasTransaction Attach a namespace name to a mosaic.
Metadata    
0x4144 AccountMetadataTransaction Associate a key-value state to an account.
0x4244 MosaicMetadataTransaction Associate a key-value state to a mosaic.
0x4344 NamespaceMetadataTransaction Associate a key-value state to a namespace.
Multisignature    
0x4155 MultisigAccountModificationTransaction Create or modify a multisig contract.
Hash Lock    
0x4148 HashLockTransaction Lock a deposit needed to announce aggregate bonded transactions.
Secret Lock    
0x4152 SecretLockTransaction Start a token swap between different chains.
0x4252 SecretProofTransaction Conclude a token swap between different chains.
Account restriction    
0x4150 AccountAddressRestrictionTransaction Allow or block incoming and outgoing transactions for a given a set of addresses.
0x4250 AccountMosaicRestrictionTransaction Allow or block incoming transactions containing a given set of mosaics.
0x4350 AccountOperationRestrictionTransaction Allow or block outgoing transactions by transaction type.
Mosaic restriction    
0x4151 MosaicGlobalRestrictionTransaction Set a global restriction to a mosaic.
0x4251 MosaicAddressRestrictionTransaction Set a mosaic restriction to a specific address.
Transfer    
0x4154 TransferTransaction Send mosaics and messages between two accounts.

Defining a transaction

Transactions are defined in a serialized form. Each transaction extends from the transaction schema definition, combining the type’s particular properties. You can find the description of the additional properties under the “Schema” section, at the end of each built-in feature description.

We recommend using the NEM2-SDK to define transactions.

import {
    Address,
    Deadline,
    NetworkCurrencyMosaic,
    NetworkType,
    PlainMessage,
    TransferTransaction
} from "nem2-sdk";

const recipientAddress = Address
    .createFromRawAddress('SD5DT3-CH4BLA-BL5HIM-EKP2TA-PUKF4N-Y3L5HR-IR54');

const transferTransaction = TransferTransaction.create(
    Deadline.create(),
    recipientAddress,
    [NetworkCurrencyMosaic.createRelative(10)],
    PlainMessage.create('Welcome To NEM'),
    NetworkType.MIJIN_TEST);

console.log(transferTransaction.serialize());

/* Outputs:
B3000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000
000000000000039054410000000000000000B986E63F170
0000090FA39EC47E05600AFA74308A7EA607D145E371B5F
4F1447BC0F00010057656C636F6D6520546F204E454D44B
262C46CEABB858096980000000000
*/

Signing a transaction

Accounts must sign transactions before announcing them to the network. Signing a transaction expresses the account’s agreement to change the network state as defined.

For example, a TransferTransaction describes who is the recipient and the quantity of mosaics to transfer. In this case, signing the transaction means to accept moving those mosaics from one account’s balance to another.

An account has to follow the next steps to sign a transaction :

  1. Get the signing bytes, which are all the bytes of the transaction except the size, signature and signer.
  2. Get the nemesis block generation hash. You can query http://localhost:3000/block/1 and copy meta.generationHash value.
  3. Prepend the nemesis block generation hash to the signing bytes.
  4. Sign the resulting string with the signer’s private key. This will give you the transaction signature.
  5. Append the signer’s signature and public key to the transaction to obtain the payload.
  6. Calculate the hash of the transaction by applying the network hashing algorithm to the first 32 bytes of signature, the signer public key, nemesis block generation hash, and the remaining transaction payload.
import {Account} from "nem2-sdk";

const privateKey = process.env.PRIVATE_KEY as string;
const generationHash = process.env.GENERATION_HASH as string;
const account = Account.createFromPrivateKey(privateKey,NetworkType.MIJIN_TEST);

const signedTransaction = account.sign(transferTransaction, generationHash);

console.log(signedTransaction.payload);

/* Outputs:
B3000000F77A8DCFCB57B81F9BE5B46738F7132998F5512
3BFF4D89DC8E5CAE1F071A040E5571F4D8DA125B243C785
DA5261F878E3DE898815F6E8F12A2C0A5F0A9C3504FA624
9E8334E3F83E972461125504AFFD3E7750AFBB3371E7B2D
22A599A3D0E3039054410000000000000000265DEE3F170
0000090FA39EC47E05600AFA74308A7EA607D145E371B5F
4F1447BC0F00010057656C636F6D6520546F204E454D44B
262C46CEABB858096980000000000
 */

console.log(signedTransaction.hash);

/* Outputs:
21C4D9583CE1887BE7187D4B65B67567B45D5E6114AEE155C0CD266B6AA6A302
 */

Announcing a transaction

Signed transactions are ready to be announced to the network. You can either use the SDK TransactionHttp service or append the payload to the request of the transaction endpoint.

import {TransactionHttp} from "nem2-sdk";

const transactionHttp = new TransactionHttp('http://localhost:3000');

transactionHttp
    .announce(signedTransaction)
    .subscribe(x => console.log(x), err => console.error(err));
curl -X PUT -H "Content-type: application/json" -d '{"payload":"B3000000F77A8DCFCB57B81F9BE5B46738F7132998F55123BFF4D89DC8E5CAE1F071A040E5571F4D8DA125B243C785DA5261F878E3DE898815F6E8F12A2C0A5F0A9C3504FA6249E8334E3F83E972461125504AFFD3E7750AFBB3371E7B2D22A599A3D0E3039054410000000000000000265DEE3F1700000090FA39EC47E05600AFA74308A7EA607D145E371B5F4F1447BC0F00010057656C636F6D6520546F204E454D44B262C46CEABB858096980000000000"}' http://localhost:3000/transaction

After announcing the transaction, the REST API will always return an OK response immediately. At this point, it is still unknown whether the transaction is valid.

../_images/transaction-cycle.png

Transaction cycle

The first stage of validation happens in the API nodes. If the transaction presents some error, the WebSocket throws a notification through the status channel. In the positive case, the transaction reaches the P2P network with an unconfirmed status. Never rely on a transaction which has an unconfirmed state. It is not clear if it will get included in a block, as it should pass a second validation.

The second validation is done before the transaction is added in a harvested block. If valid, the harvester stores the transaction in a block, and it reaches the confirmed status.

Continuing the previous example, the transaction gets processed and the amount stated gets transferred from the signer’s account to the recipient’s account. Additionally, the transaction fee is deducted from the signer’s account.

The transaction has zero confirmations at this point. When another block is added to the blockchain, the transaction has one confirmation. The next block added to the chain will give it two confirmations and so on.

Rollbacks

Blockchains are designed in a way that under certain circumstances recent blocks need to be rolled back. These are essential to resolve forks of the blockchain.

The rewrite limit is the maximum number of blocks that can be rolled back. Hence, forks can only be resolved up to a certain depth too.

Catapult has a rewrite limit of 40 blocks. Once a transaction has more than 40 confirmations, it cannot be reversed.

Guides

Transaction schemas

Transaction

Serialization of a transaction.

Inlines:

Property Type Description
max_fee Amount Maximum fee allowed to spend for the transaction.
deadline Timestamp Number of milliseconds elapsed since the creation of the nemesis block. If a transaction does not get included in a block before the deadline is reached, it is deleted. Deadlines are only allowed to lie up to 24 hours ahead.

EmbeddedTransactionHeader

Binary layout for an embedded transaction header.

Inlines:

Property Type Description
embeddedTransactionHeader_Reserved1 uint32 Reserved padding to align end of EmbeddedTransactionHeader on 8-byte boundary.

EmbeddedTransaction

Serialization of an aggregate inner transaction.

Inlines:

Entity schemas

SizePrefixedEntity

Serialization of an entity that has a prefixed size.

Property Type Description
size unit32 Size of the transaction.

VerifiableEntity

Serialization of an entity that should be signed by an account.

Property Type Description
verifiableEntityHeader_Reserved1 uint32 reserved padding to align Signature on 8-byte boundary.
signature Signature Entity signature generated by the signer.

EntityBody

Serialization of an entity. An entity could be a block or a transaction.

Property Type Description
signerPublicKey Key Public key of the signer of the entity.
entityBody_Reserved1 uint32 Reserved padding to align end of EntityBody on 8-byte boundary.
version uint8 Version of the structure.
network Network Entity network.
type EntityType Entity type.

NetworkType

Enumeration: uint8

Id Description
0x68 (MAIN_NET) Public network.
0x98 (TEST_NET) Public test network.
0x60 (MIJIN) Private network.
0x90 (MIJIN_TEST) Private test network.

EntityType

Enumeration: uint16

Id Description
0x0000 Reserved.

Continue: Fees.