Qucik Learning Symbol Section 4

Transaction

Updating data on the blockchain is done by announcing transactions to the network.

4.1 Transaction lifecycle

Below is a description of the lifecycle of a transaction:

  • Transaction creation – Create transactions in an acceptable format for the blockchain.
  • Signature – Sign the transaction with the account's privatekey.
  • Announcement – Announce a signed transaction to any node on the network.
  • Unconfirmed state transactions – Transactions accepted by a node are propagated to all nodes as unconfirmed state transactions. ∗ In a case where the maximum fee set for a transaction is not enough for the minimum fee set for each node, it will not be propagated to that node.
  • Confirmed transaction – When an unconfirmed transaction is contained in a subsequent new block (generated approximately every 30 seconds), it becomes an approved transaction.
  • Rollbacks – Transactions that could not reach a consensus agreement between nodes are rolled back to an unconfirmed state. ∗ Transactions that have expired or overflowed the cache are truncated.
  • Finalise – Once the block is finalised by the finalisation process of the voting node, the transaction can be treated as final and data can no longer be rolled back.
  • These are the most basic information for operating a blockchain. You should also see how to generate accounts from private keys and how to generate classes that deal only with public keys and addresses.

    4.1.1 What is a block?

    Blocks are generated approximately every 30 seconds and are synchronised with other nodes on a block-by-block basis with priority given to transactions that have paid higher fees. If synchronisation fails, it is rolled back and the network repeats this process until consensus agreement is reached across all nodes.

    4.2 Transaction creation

    First of all, start with creating the most basic transfer transaction.

    
    $bobKey = $facade->createAccount(PrivateKey::random());
    echo $bobKey->address . PHP_EOL;
    
    
    > TDCTNJQT27NMIMGAQYWBUG6MCLBXYI2OOPVZ76I
    

    Create transaction.

    
    // aliceの秘密鍵からアカウント生成
    $aliceKey = $facade->createAccount(new PrivateKey($alicePrivateKey));
    
    $messageData = "\0hello, symbol!";
    $tx = new TransferTransactionV1(
      network: new NetworkType(NetworkType::TESTNET),
      signerPublicKey: $aliceKey->publicKey,
      deadline: new Timestamp($facade->now()->addHours(2)),
      recipientAddress: $bob->address,
      mosaics: [
        new UnresolvedMosaic(
          mosaicId: new UnresolvedMosaicId('0x72C0212E67A08BCE'),
          amount: new Amount(1000000)
        )
      ],
      message: $messageData
    );
    
    $facade->setMaxFee($transferTransaction, 100);  // 手数料
    var_dump($tx);
    
    
    object(SymbolSdk\Symbol\Models\TransferTransactionV1)#71 (14) {
      ["recipientAddress"]=>
      object(SymbolSdk\Symbol\Models\UnresolvedAddress)#68 (1) {
        ["binaryData"]=>
        string(24) "��!�OX�p�#�:���(���"
      }
      ["mosaics"]=>
      array(1) {
        [0]=>
        object(SymbolSdk\Symbol\Models\UnresolvedMosaic)#76 (2) {
          ["mosaicId"]=>
          object(SymbolSdk\Symbol\Models\UnresolvedMosaicId)#77 (2) {
            ["size"]=>
            int(8)
            ["value"]=>
            int(8268645399043017678)
          }
          ["amount"]=>
          object(SymbolSdk\Symbol\Models\Amount)#78 (2) {
            ["size"]=>
            int(8)
            ["value"]=>
            int(1000000)
          }
        }
      }
      ["message"]=>
      string(15) "hello, symbol!"
      ["transferTransactionBodyReserved_1":"SymbolSdk\Symbol\Models\TransferTransactionV1":private]=>
      int(0)
      ["transferTransactionBodyReserved_2":"SymbolSdk\Symbol\Models\TransferTransactionV1":private]=>
      int(0)
      ["signature"]=>
      object(SymbolSdk\Symbol\Models\Signature)#80 (1) {
        ["binaryData"]=>
        string(64) ""
      }
      ["signerPublicKey"]=>
      object(SymbolSdk\Symbol\Models\PublicKey)#73 (1) {
        ["binaryData"]=>
        string(32) "%�5�#ܼ�ez4�����JmEr�k�OQM���"
      }
      ["version"]=>
      int(1)
      ["network"]=>
      object(SymbolSdk\Symbol\Models\NetworkType)#75 (1) {
        ["value"]=>
        int(152)
      }
      ["type"]=>
      object(SymbolSdk\Symbol\Models\TransactionType)#79 (1) {
        ["value"]=>
        int(16724)
      }
      ["fee"]=>
      object(SymbolSdk\Symbol\Models\Amount)#81 (2) {
        ["size"]=>
        int(8)
        ["value"]=>
        int(19100)
      }
      ["deadline"]=>
      object(SymbolSdk\Symbol\Models\Timestamp)#72 (2) {
        ["size"]=>
        int(8)
        ["value"]=>
        int(54392061979)
      }
      ["verifiableEntityHeaderReserved_1":"SymbolSdk\Symbol\Models\Transaction":private]=>
      int(0)
      ["entityBodyReserved_1":"SymbolSdk\Symbol\Models\Transaction":private]=>
      int(0)
    }
    

    Each setting is explained below.

    Expiry date

    2 hours is the SDK's default setting. A maximum of 6 hours can be specified.

    
    new Timestamp($facade->now()->addHours(2))
    

    Message

    In a message field, up to 1023 bytes can be attached to a transaction. Also binary data can be sent as raw data.

    Empty message

    
    $messageData = "";?
    

    Plain message

    To be displayed in Explorer, etc., it is necessary to append \\0 at the beginning.

    
    $messageData = "\0hello, symbol!";
    

    Encrypted message

    When encryption is performed using MessageEncoder, the message type 0x01, which represents a ciphertext message, is automatically added.

    
    $aliceMesgEncoder = new MessageEncoder($aliceKey);
    $encryptedMessage = $aliceMesgEncoder->encode($bobKey->publicKey(), $message);
    

    Maximum fee

    Although paying a small additional fee is better to ensure a transaction is successful, having some knowledge about network fees is a good idea. The account specifies the maximum fee it is willing to pay when it creates the transaction. On the other hand, nodes try to harvest only the transactions with the highest fees into a block at a time. This means that if there are many other transactions that are willing to pay more, the transaction will take longer to be approved. Conversely, if there are many other transactions that want to pay less and your maximum fee is larger, then the transaction will be processed with a fee below the maximum value you set.

    The fee paid is determined by a transaction size x feeMultiplier. If it was 176 bytes and your maxFee is set at 100, 17600µXYM = 0.0176XYM is the maximum value you allow to be paid as a fee for the transaction. There are two ways to specify this: as feeMultiplier = 100 or as maxFee = 17600.

    To specify as feeMultiprier = 100

    
    $facade->setMaxFee($transferTransaction, 100);
    

    4.3 Signature and announcement

    Sign the transaction which you create with the private key and announce it to any node.

    Signature

    
    $signature = $aliceKey->signTransaction($transferTransaction);
    $payload = $facade->attachSignature($transferTransaction, $signature);
    var_dump($payload);
    

    Sample output

    
    array(1) {
      ["payload"]=>
      string(382) "BF0000000000000071B2D3DA6B83E6904DEB1EE5AE259D6F51B71E742B3F4D5B9EC394BADC844A1574F9418F0349D825AAD836100F39F0AB87EC0BF19BE8E21B1AB94D0AC11B780625189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B00000000019854419C4A0000000000000CB455A40C00000098D02DDEA92E7186B5321831A58554E7B6EB58454B08161E0F00010000000000CE8BA0672E21C07240420F00000000000068656C6C6F2C2073796D626F6C21"
    }
    

    Announcement

    
    $config = new Configuration();
    $config->setHost($NODE_URL);
    $client = new GuzzleHttp\Client();
    $apiInstance = new TransactionRoutesApi($client, $config);
    
    try {
      $result = $apiInstance->announceTransaction($payload);
      echo $result . PHP_EOL;
    } catch (Exception $e) {
      echo 'Exception when calling TransactionRoutesApi->announceTransaction: ', $e->getMessage(), PHP_EOL;
    }
    
    ※ If you are using an IDE, $apiInstance->announceTransaction($payload), you may get a warning when you specify the payload here, but don't worry about it.
    
    {
        "message": "packet 9 was pushed to the network via \/transactions"
    }
    

    As in the script above, a response will be sent: packet n was pushed to the network, this means that the transaction has been accepted by the node. However, this only means that there were no anomalies in the formatting of the transaction. In order to maximise the response speed of the node, Symbol returns the response of the received result and disconnects the connection before verifying the content of the transaction. The response value is merely the receipt of this information. If there is an error in the format, the message response will be as follows:

    Sample output of response if announcement fails

    
    Uncaught Error: {
    "statusCode":409,
    "statusMessage":"Unknown Error",
    "body":
    "{\"code\":\"InvalidArgument\",\"message\":\"payload has an invalid format\"}"
    }
    

    4.4 Confirmation

    4.4.1 Status confirmation

    Check the status of transactions accepted by the node.

    
    $hash = $facade->hashTransaction($transferTransaction);
    $txStatusApi = new TransactionStatusRoutesApi($client, $config);
    
    try {
      $txStatus = $txStatusApi->getTransactionStatus($hash);
      var_dump($txStatus);
    } catch (Exception $e) {
      echo 'Exception when calling TransactionRoutesApi->announceTransaction: ', $e->getMessage(), PHP_EOL;
    }
    

    Sample output

    
    object(SymbolRestClient\Model\TransactionStatusDTO)#111 (2) {
      ["openAPINullablesSetToNull":protected]=>
      array(0) {
      }
      ["container":protected]=>
      array(5) {
        ["group"]=>
        string(11) "unconfirmed"
        ["code"]=>
        string(7) "Success"
        ["hash"]=>
        string(64) "D944914B44D1E210CF9FE7E7BA9C27ACBDB9B8C76E4844CE7E530B564189C323"
        ["deadline"]=>
        string(11) "54299100360"
        ["height"]=>
        string(1) "0"
      }
    }
    

    When it is approved, the output shows group: "confirmed" .

    If it was accepted but an error occurred, the output will show as follows. Rewrite the transaction and try announcing it again.

    
    object(SymbolRestClient\Model\TransactionStatusDTO)#111 (2) {
      ["openAPINullablesSetToNull":protected]=>
      array(0) {
      }
      ["container":protected]=>
      array(5) {
        ["group"]=>
        string(6) "failed"
        ["code"]=>
        string(33) "Failure_Core_Insufficient_Balance"
        ["hash"]=>
        string(64) "1DC2808BC3BBAD6F8C9ECDC1C5F0523D681E875CA414944D73CCCB592E7775CF"
        ["deadline"]=>
        string(11) "54299158295"
        ["height"]=>
        NULL
      }
    }
    

    If the transaction has not been accepted, the output will show the ResourceNotFound error as follows.

    
    response:
    {"code":"ResourceNotFound","message":"no resource exists with id '066A063559C2D4EF2EA3222A9BA46193520915DE24EA4B3E601910 (truncated...)}
    

    This error occurs when the maximum fee specified in the transaction is less than the minimum fee set by the node, or if a transaction that is required to be announced as an aggregate transaction is announced as a single transaction.

    4.4.2 Approval Confirmation

    It takes around 30 seconds for a transaction to be approved for the block.

    Check with the Explorer

    Search in Explorer using the hash value that can be retrieved with signedTx.hash.
    
    $hash = $facade->hashTransaction($transferTransaction);
    echo $hash . PHP_EOL;
    
    
    > "BAD83010F0A707A8ED0AF9D5BFDDBF8226878F6921CE75C7E75BBE50F869870B"
    

    Mainnet https://symbol.fyi/transactions/BAD83010F0A707A8ED0AF9D5BFDDBF8226878F6921CE75C7E75BBE50F869870B
    Testnet https://testnet.symbol.fyi/transactions/BAD83010F0A707A8ED0AF9D5BFDDBF8226878F6921CE75C7E75BBE50F869870B

    Check with the SDK

    
    try {
      $result = $apiInstance->getConfirmedTransaction($hash);
      echo $result . PHP_EOL;
    } catch (Exception $e) {
      echo 'Exception when calling TransactionRoutesApi->announceTransaction: ', $e->getMessage(), PHP_EOL;
    }
    

    Sample output

    
    {
        "id": "669CABEA527B051AC20A62DF",
        "meta": {
            "height": "1593561",
            "hash": "7F6E7537D731307CCB6F9DDF62E737326071038851939623FF1AB56C83D2FBDF",
            "merkleComponentHash": "7F6E7537D731307CCB6F9DDF62E737326071038851939623FF1AB56C83D2FBDF",
            "index": 0,
            "timestamp": "54293190821",
            "feeMultiplier": 100
        },
        "transaction": {
            "size": 191,
            "signature": "08BEC8BC4B00733F6E029F92F2B2A736BFAFD748D818BEB98DFCF9FAC36AC6823A6A53A4F16FF1B6A49B0ECAA99FD31B0BD460A876EAD0C1A5D1990356A65105",
            "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
            "version": 1,
            "network": 152,
            "type": 16724,
            "maxFee": "19100",
            "deadline": "54300378357",
            "recipientAddress": "98E521BD0F024F58E670A023BF3A14F3BECAF0280396BED0",
            "mosaics": [
                {
                    "id": "72C0212E67A08BCE",
                    "amount": "1000000"
                }
            ],
            "message": "0068656C6C6F2C2073796D626F6C21"
        }
    }
    

    ■Note Even when a transaction is confirmed in a block, the confirmation of the transaction still has the possibility of being revoked if a rollback occurs. After a block has been approved, the probability of a rollback occurring decreases as the approval process proceeds for several blocks. In addition, waiting for the finalisation block, which is carried out by voting nodes, ensures that the recorded data is certain.

    ■Sample script After announcing the transaction, it is useful to see the following script to keep track of the chain status.The reason for putting “sleep” in the middle of the message is that it may go to check the status before the announcement and return an error.

    
    sleep(2);
    $hash = $facade->hashTransaction($transferTransaction);
    echo "\n===トランザクションハッシュ===" . PHP_EOL;
    echo $hash . PHP_EOL;
    
    $txStatusApi = new TransactionStatusRoutesApi($client, $config);
    
    try {
      $txStatus = $txStatusApi->getTransactionStatus($hash);
      echo "\n===ステータスの確認===" . PHP_EOL;
      var_dump($txStatus);
    } catch (Exception $e) {
      echo 'Exception when calling TransactionRoutesApi->announceTransaction: ', $e->getMessage(), PHP_EOL;
    }
    
    sleep(1);
    /**
     * 承認確認
     */
    try {
      $result = $apiInstance->getConfirmedTransaction($hash);
      echo "\n===承認確認===" . PHP_EOL;
      echo $result . PHP_EOL;
    } catch (Exception $e) {
      echo 'Exception when calling TransactionRoutesApi->announceTransaction: ', $e->getMessage(), PHP_EOL;
    }
    

    4.5 Transaction history

    Get a list of the transaction history sent and received by Alice.

    
    try {
      $result = $apiInstance->searchConfirmedTransactions(
        address: $aliceKey->address,
        embedded: "true",
      );
      echo "\n===トランザクション履歴===" . PHP_EOL;
      var_dump($result);
    } catch (\Throwable $th) {
      echo 'Exception when calling TransactionRoutesApi->searchConfirmedTransactions: ', $th->getMessage(), PHP_EOL;
    }
    

    ※ If you use an IDE, you may get a warning message because embedded expects a bool type, but here we pass the string true.

    Sample output

    
    {
        "data": [
            {
                "id": "669C9D0B527B051AC20A61DF",
                "meta": {
                    "height": "1593459",
                    "hash": "5FDA8DB2C16B4C0C3F6C22E6856B2A8CFAC5001020F7ED3151069D879A0BE29D",
                    "merkleComponentHash": "5FDA8DB2C16B4C0C3F6C22E6856B2A8CFAC5001020F7ED3151069D879A0BE29D",
                    "index": 0,
                    "timestamp": "54289384247",
                    "feeMultiplier": 534
                },
                "transaction": {
                    "size": 187,
                    "signature": "E9E4E49235FC46D892B77DDC37CB42D827556860D1C609DEF171A4EC698C85744FBD579641E0765CA6B2D9E4E12DCEFF9E6C9473CF5948CFC17BA7A566444F0A",
                    "signerPublicKey": "81EA7C15E7EC06261C9F654F54EAC4748CFCF00E09A8FE47779ACD14A7602004",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "100000",
                    "deadline": "54296567552",
                    "recipientAddress": "98E521BD0F024F58E670A023BF3A14F3BECAF0280396BED0",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "500000000"
                        }
                    ],
                    "message": "00476F6F64204C75636B21"
                }
            },
            {
                "id": "669C9D31527B051AC20A61E3",
                "meta": {
                    "height": "1593460",
                    "hash": "A39F0A79CD87D4247B00C2397875803AD2103542B6B3C7F485F80A4A4D613746",
                    "merkleComponentHash": "A39F0A79CD87D4247B00C2397875803AD2103542B6B3C7F485F80A4A4D613746",
                    "index": 0,
                    "timestamp": "54289422373",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "3F989538EEEBA80AB3394475B8BA93B40B75277B4D12D9003998E20CFBE66721E38B606184A5DA704257B8D766FAEE283901EB0A3945B97C8D18AFB7D83CA104",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54296609500",
                    "recipientAddress": "988EF2B2B89F6BC742C3902F8FCD66CF3B096A3B970DCE0D",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            },
            {
                "id": "669C9D7A527B051AC20A61E9",
                "meta": {
                    "height": "1593462",
                    "hash": "963BFB1866067979D6105053DB85BA190DF22E0ABE39732596361B8788EDA664",
                    "merkleComponentHash": "963BFB1866067979D6105053DB85BA190DF22E0ABE39732596361B8788EDA664",
                    "index": 0,
                    "timestamp": "54289494625",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "71B2D3DA6B83E6904DEB1EE5AE259D6F51B71E742B3F4D5B9EC394BADC844A1574F9418F0349D825AAD836100F39F0AB87EC0BF19BE8E21B1AB94D0AC11B7806",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54296687628",
                    "recipientAddress": "98D02DDEA92E7186B5321831A58554E7B6EB58454B08161E",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            },
            {
                "id": "669CA1CC527B051AC20A6227",
                "meta": {
                    "height": "1593492",
                    "hash": "5B1974CD5B0958F5A716151EA677A28C20B348920D65E8ECAFEA5C52726E6CD4",
                    "merkleComponentHash": "5B1974CD5B0958F5A716151EA677A28C20B348920D65E8ECAFEA5C52726E6CD4",
                    "index": 0,
                    "timestamp": "54290601924",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "2ABCC254980A9C662D3A435149E52891FFCC7576AF19F9CEE25053E34A3543EA216A79D3884DFC7770993D32B68EB65ACAFC7A677BBFF363EA0432D725DF060C",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54297798137",
                    "recipientAddress": "98A1947584CC5BF18F0C31C76BEB6785639E710DF8D0C65A",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            },
            {
                "id": "669CA3A1527B051AC20A6243",
                "meta": {
                    "height": "1593505",
                    "hash": "45AE0769D78F2CF7CBD86657B3E0B0E1AAE63D30EA53708B032C00A1A22D0BC0",
                    "merkleComponentHash": "45AE0769D78F2CF7CBD86657B3E0B0E1AAE63D30EA53708B032C00A1A22D0BC0",
                    "index": 0,
                    "timestamp": "54291069705",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "F484662FCF3E8C6A5AED6CBF145709191F766F75496C712B4096B1A3B1CE1DF9B19C7E6B4EAED093B5C6649C91315F4ADC2F05537389BD6B773C888D02192106",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54298265506",
                    "recipientAddress": "98E521BD0F024F58E670A023BF3A14F3BECAF0280396BED0",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            },
            {
                "id": "669CA651527B051AC20A6272",
                "meta": {
                    "height": "1593524",
                    "hash": "A5C897E3FACFEBE21C0E7E5AFC34B03CB69FFE7401E9EB526A518B1CD9909B30",
                    "merkleComponentHash": "A5C897E3FACFEBE21C0E7E5AFC34B03CB69FFE7401E9EB526A518B1CD9909B30",
                    "index": 0,
                    "timestamp": "54291758600",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "4A299DCB86E3394778EDAAF08784692C62E69FBC26E6C65CD097885558F4B6869740BC4713CD91B45C42A10965303BED2C2515B35EB9533CAAA10D96978E100B",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54298910859",
                    "recipientAddress": "98E521BD0F024F58E670A023BF3A14F3BECAF0280396BED0",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            },
            {
                "id": "669CA651527B051AC20A6273",
                "meta": {
                    "height": "1593524",
                    "hash": "03A4710884D72B960574DFD389ED0F2484A4FF3F25C07ABA5E5645D57830B415",
                    "merkleComponentHash": "03A4710884D72B960574DFD389ED0F2484A4FF3F25C07ABA5E5645D57830B415",
                    "index": 1,
                    "timestamp": "54291758600",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "CEF6B254B5891E8A003930F41C52315D8A42D51EF04874E20EA63618FF8B3EF5F5CFA6F8D6100CCCFB34F9F3C5255AEB8CB40CBD8481B50B46A9FC59DC1ADE08",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54298936740",
                    "recipientAddress": "98E521BD0F024F58E670A023BF3A14F3BECAF0280396BED0",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            },
            {
                "id": "669CA685527B051AC20A6277",
                "meta": {
                    "height": "1593525",
                    "hash": "24F6DDD9A53198948EBDC864C5CC8072D08ECA320F2803B45C78A84B12AAED87",
                    "merkleComponentHash": "24F6DDD9A53198948EBDC864C5CC8072D08ECA320F2803B45C78A84B12AAED87",
                    "index": 0,
                    "timestamp": "54291809907",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "3CAE1F2908409365391D87C48B5C8C3C5C11CD920C7CCA8A8C738FB78140130811AAECA54AA0A235E2956C3B1867280156EF3EEA0609826B617C2CE934901E0F",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54299008654",
                    "recipientAddress": "98E521BD0F024F58E670A023BF3A14F3BECAF0280396BED0",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            },
            {
                "id": "669CA709527B051AC20A627F",
                "meta": {
                    "height": "1593528",
                    "hash": "D944914B44D1E210CF9FE7E7BA9C27ACBDB9B8C76E4844CE7E530B564189C323",
                    "merkleComponentHash": "D944914B44D1E210CF9FE7E7BA9C27ACBDB9B8C76E4844CE7E530B564189C323",
                    "index": 0,
                    "timestamp": "54291942199",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "EA54DC04B9E2039090FC73E4B19EC6063542FB41978C6C6A327C1DDA3F04678F50D4F76EF5D0DFC5EB38C002D3F39219C1278DF9BDD2F83954DA1C4A3001E709",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54299100360",
                    "recipientAddress": "98E521BD0F024F58E670A023BF3A14F3BECAF0280396BED0",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            },
            {
                "id": "669CA74F527B051AC20A6285",
                "meta": {
                    "height": "1593530",
                    "hash": "9E2E98FE88AEA9685E0B0A87E56C17F436F429A452CC3A7B187AC37E2B26DB79",
                    "merkleComponentHash": "9E2E98FE88AEA9685E0B0A87E56C17F436F429A452CC3A7B187AC37E2B26DB79",
                    "index": 0,
                    "timestamp": "54292012549",
                    "feeMultiplier": 100
                },
                "transaction": {
                    "size": 191,
                    "signature": "0A550C24171133AAE9349841E3EE919BC9B410CC94CB40C568031901CF0ABB2974F9DFE88068547A06044CB97F4A0315A648D0EEAB163C8A76E5AD2C086C320F",
                    "signerPublicKey": "25189135BF2307DCBCD1657A34ABC3FDEEC04A126D4572876BCA4F514DB5AC9B",
                    "version": 1,
                    "network": 152,
                    "type": 16724,
                    "maxFee": "19100",
                    "deadline": "54299208979",
                    "recipientAddress": "98E521BD0F024F58E670A023BF3A14F3BECAF0280396BED0",
                    "mosaics": [
                        {
                            "id": "72C0212E67A08BCE",
                            "amount": "1000000"
                        }
                    ],
                    "message": "0068656C6C6F2C2073796D626F6C21"
                }
            }
        ],
        "pagination": {
            "pageNumber": 1,
            "pageSize": 10
        }
    }
    

    4.5.1 Differences in messages when creating Tx payloads

    【Not yet verified and will be written after verification】

    4.6 Aggregate Transactions

    Aggregate transactions can merge multiple transactions into one. Symbol’s public network supports aggregate transactions containing up to 100 inner transactions (involving up to 25 different cosignatories). The content covered in subsequent chapters includes functions that require an understanding of aggregate transactions. This chapter introduces only the simplest of aggregate transactions.

    
    $bobKey = $facade->createAccount(PrivateKey::random());
    $bobAddress = $bobKey->address;
    $carolKey = $facade->createAccount(PrivateKey::random());
    $carolAddress = $carolKey->address;
    
    // アグリゲートTxに含めるTxを作成
    $innerTx1 = new EmbeddedTransferTransactionV1(
      network: new NetworkType(NetworkType::TESTNET),
      signerPublicKey: $aliceKey->publicKey,
      recipientAddress: $carolAddress,
      message: "\0hello, carol!"
    );
    
    $innerTx2 = new EmbeddedTransferTransactionV1(
      network: new NetworkType(NetworkType::TESTNET),
      signerPublicKey: $aliceKey->publicKey,
      recipientAddress: $bobAddress,
      message: "\0hello, bob!"
    );
    
    // マークルハッシュの算出
    $embeddedTransactions = [$innerTx1, $innerTx2];
    $merkleHash = $facade->hashEmbeddedTransactions($embeddedTransactions);
    
    // アグリゲートTx作成
    $aggregateTx = new AggregateCompleteTransactionV2(
      network: new NetworkType(NetworkType::TESTNET),
      signerPublicKey: $aliceKey->publicKey,
      deadline: new Timestamp($facade->now()->addHours(2)),
      transactionsHash: $merkleHash,
      transactions: $embeddedTransactions
    );
    $facade->setMaxFee($aggregateTx, 100);  // 手数料
    
    // 署名
    $sig = $aliceKey->signTransaction($aggregateTx);
    $payload = $facade->attachSignature($aggregateTx, $sig);
    // アナウンス
    try {
      $result = $apiInstance->announceTransaction($payload);
      echo $result . PHP_EOL;
    } catch (Exception $e) {
      echo 'Exception when calling TransactionRoutesApi->announceTransaction: ', $e->getMessage(), PHP_EOL;
    }
    

    First, create the transactions to be included in the aggregate transaction. It is not necessary to specify a Deadline at this time. When listing, add toAggregate to the generated transaction and specify the publickey of the sender account. Note that the sender and signing accounts do not always match. This is because of the possibility of scenarios such as 'Alice signing the transaction that Bob sent', which will be explained in subsequent chapters. This is the most important concept in using transactions on the Symbol blockchain. The transactions in this chapter are sent and signed by Alice, so the signature on the aggregate bonded transaction also specifies Alice.

    4.6.1 Maximum fee on aggregate transactions

    Aggregate transactions, like regular transactions, can be executed either by specifying the maximum fee directly or by using feeMultiplier. In the previous example, we used the method of specifying the maximum fee directly. Here we introduce the method of specifying the maximum fee by feeMultiplier.

    
    $requiredCosignatures = 1; // 必要な連署者の数を指定
    $calculatedCosignatures = $requiredCosignatures > count($aggregateTx->cosignatures)
        ? $requiredCosignatures
        : count($aggregateTx->cosignatures);
    $sizePerCosignature = 8 + 32 + 64;
    $calculatedSize = $aggregateTx->size() -
        count($aggregateTx->cosignatures) * $sizePerCosignature +
        $calculatedCosignatures * $sizePerCosignature;
    
    $aggregateTx->fee = new Amount($calculatedSize * 100);  // 手数料
    

    4.7 Tips for use

    Proof of existence

    The chapter on Accounts described how to sign and verify data by account. Putting this data into a transaction that is confirmed on the blockchain makes it impossible to delete the fact that an account has proved the existence of certain data at a certain time. It can be considered to have the same meaning as the possession between interested parties of a time-stamped electronic signature.(Legal decisions are left to experts)

    The blockchain updates data such as transactions with the existence of this "indelible fact that the account has proved". And also the blockchain can be used as proof of knowledge of a fact that nobody should have known about yet. This section describes two patterns in which data whose existence has been proven can be put on a transaction.

    Digital data hash value (SHA256) output method

    The existence of a file can be proved by recording its digest value in the blockchain.

    The calculation of the hash value using SHA256 for files in each operating system is as follows.

    
    #Windows
    certutil -hashfile WINファイルパス SHA256
    #Mac
    shasum -a 256 MACファイルパス
    #Linux
    sha256sum Linuxファイルパス
    

    4.7.1 Splitting large data

    As the payload of a transaction can only contain 1023 bytes. Large data is split up and packed into the payload to make an aggregate transaction.

    
    $bigdata = "C00200000000000093B0B985101C1BDD1BC2BF30D72F35E34265B3F381ECA464733E147A4F0A6B9353547E2E08189EF37E50D271BEB5F09B81CE5816BB34A153D2268520AF630A0A0E5C72B0D5946C1EFEE7E5317C5985F106B739BB0BC07E4F9A288417B3CD6D26000000000198414140770200000000002A769FB40000000076B455CFAE2CCDA9C282BF8556D3E9C9C0DE18B0CBE6660ACCF86EB54AC51B33B001000000000000DB000000000000000E5C72B0D5946C1EFEE7E5317C5985F106B739BB0BC07E4F9A288417B3CD6D26000000000198544198205C1A4CE06C45B3A896B1B2360E03633B9F36BF7F22338B000000000000000066653465353435393833444430383935303645394533424446434235313637433046394232384135344536463032413837364535303734423641303337414643414233303344383841303630353343353345354235413835323835443639434132364235343233343032364244444331443133343139464435353438323930334242453038423832304100000000006800000000000000B2D4FD84B2B63A96AA37C35FC6E0A2341CEC1FD19C8FFC8D93CCCA2B028D1E9D000000000198444198205C1A4CE06C45B3A896B1B2360E03633B9F36BF7F2233BC089179EBBE01A81400140035383435344434373631364336433635373237396800000000000000B2D4FD84B2B63A96AA37C35FC6E0A2341CEC1FD19C8FFC8D93CCCA2B028D1E9D000000000198444198205C1A4CE06C45B3A896B1B2360E03633B9F36BF7F223345ECB996EDDB9BEB1400140035383435344434373631364336433635373237390000000000000000B2D4FD84B2B63A96AA37C35FC6E0A2341CEC1FD19C8FFC8D93CCCA2B028D1E9D5A71EBA9C924EFA146897BE6C9BB3DACEFA26A07D687AC4A83C9B03087640E2D1DDAE952E9DDBC33312E2C8D021B4CC0435852C0756B1EBD983FCE221A981D02";
    
    $payloads = [];
    for ($i = 0; $i < strlen($bigdata) / 1023; $i++) {
        $payloads[] = substr($bigdata, $i * 1023, 1023);
    }
    
    print_r($payloads);