Windows と TypeScript ではじめる Symbol 通信 11【ブロック情報】


さて、今回からは普段使いしないところを取得していきます。

## ブロックデータの取得

### ノードへリクエスト

ブロック情報を取得するパケットタイプは、`0ｘ004`です。ペイロードにブロック高を指定します。

```typescript:Catapult.ts
/** パケットタイプ */
private PacketType = {
  PULL_BLOCK: 0x0_04,
  CHAIN_STATISTICS: 0x0_05,
  PUSH_TRANSACTIONS: 0x0_09,
  PUSH_PARTIAL_TRANSACTIONS: 0x1_00,
  NODE_DISCOVERY_PULL_PING: 0x1_11,
  TIME_SYNC_NETWORK_TIME: 0x1_20,
  FINALIZATION_STATISTICS: 0x1_32,
  UNLOCKED_ACCOUNTS: 0x3_04,
}

async getBlock(blockHeight: bigint) {
  let block: models.Block | undefined = undefined
  try {
    const payloadBuffer = new ArrayBuffer(8)
    const payloadDataView = new DataView(payloadBuffer)
    payloadDataView.setBigUint64(0, blockHeight, true)
    const socketData = await this.request(
      this.PacketType.PULL_BLOCK,
      new Uint8Array(payloadBuffer)
    )
    if (socketData) block = models.BlockFactory.deserialize(socketData)
  } catch (e) {
    if (e instanceof Error) console.error(e.message)
    else console.error(e)
  } finally {
    this.close()
  }
  return block
}
```

### レスポンスデータの解析

レスポンスデータの解析は、SDK の models にある BlockFactory クラスのデシリアライザを使用しています。

### メインの作成

実行するコードを作成します。

```typescript:src/mainPullBlock.ts
import { Catapult } from './Catapult.js'

const catapult = new Catapult(
  'cert/ca.crt.pem',
  'cert/node.crt.pem',
  'cert/node.key.pem',
  '127.0.0.1'
)

const block = await catapult.getBlock(1957514n)
if (block) console.log(JSON.stringify(block.toJson(), null, 2))
```

### 実行

```posh
yarn tsx .\src\mainPullBlock.ts
```

実行すると以下の様にブロック情報が出力されます。

```plaintext
socket connected.
{
  "signature": "0506F8B9B00A5FDABBFDFB2702862DB6ED9258A80049C25E9D381AB0F8DBB7546A869F603F41BE6CEE2F3EFADD55B4B7739D7157E5B80DEF8E474DC1593DB10A",
  "signerPublicKey": "08FE7A2FEF4660B2E9967C7B457DB8ED280B468E51A608F4DEB8DC400D37B277",
  "version": 1,
  "network": 152,
  "type": 33091,
  "height": "1957514",
  "timestamp": "66642051954",
  "difficulty": "10000000000000",
  "generationHashProof": {
    "gamma": "B3BB75611E082872BC454EADAB81776932308982F36A1F0EA9EB74EFE68F5556",
    "verificationHash": "5D97A1F67DB7AAA8D44E3DB526786F74",
    "scalar": "FAD25677C476173F4919E39B6F2C303AF4B9E9F2534CBA4CC251A9B6CDAE580B"
  },
  "previousBlockHash": "A3EA535C74EA28DC658F5E67090FB6F40727FE223BF1B0EC3C15794C96D06E35",
  "transactionsHash": "3916254AB161D5B50402FE362D909EAAF6795BB76508999EE0E6DE352FE9C224",
  "receiptsHash": "854EB4729606CA953825DF5DE4010ABEB2B5587A4FFB7EBA19236251CD821CA7",
  "stateHash": "5D1E5D787B131A0082364E293F0B75F9D937B5B594F9E4C9411775BEE88DFEA4",
  "beneficiaryAddress": "98E66F6BA1517F5BFB7674F82F628C410C58F057C7AFE33C",
  "feeMultiplier": 100,
  "transactions": [
    {
      "signature": "EE2AA0CC9EE40FE30534989CD6C6E259D368349F7CAD71C71EE201744C5A57DFA6A88354899C778F90B284071399B84FD58C07CE49D7D45B075F1397EDAB070B",
      "signerPublicKey": "769BCFBFFCB5287A902BD83B5CAACB5C2EEFA7FE6129553CA237AD2BCA147A59",
      "version": 2,
      "network": 152,
      "type": 16705,
      "fee": "49600",
      "deadline": "66649216943",
      "transactionsHash": "820A8646B1723B2B18AEC050EB5918574F2AEA846796384A0C19ADDE02206BC1",
      "transactions": [
        {
          "signerPublicKey": "C2C3344415044113C1AA1C119F1CC9EC072000B11BE987A3A9554781EF02F5A2",
          "version": 1,
          "network": 152,
          "type": 16724,
          "recipientAddress": "981797FA9D96B16786AA38F66C6DA7C06B9232442AAE031F",
          "mosaics": [],
          "message": "0048656C6C6F206163636F756E74412046726F6D204D756C7469736967204163636F756E7421"
        }
      ],
      "cosignatures": [
        {
          "version": "0",
          "signerPublicKey": "561B1F2C7A2BB46279E2CC26511755D7DBC55E784F1BF2ED78B938BBEE2C04B3",
          "signature": "16C8B20F5128154ADB3A5E79ABB327994C7E4CBEC88C4AA51C313677B9A4576C7AFD21827782CC253887C1D7E4B658F260EB20D0CA8F53AD3193EF39B097F009"
        },
        {
          "version": "0",
          "signerPublicKey": "958B9422915F544BA56857B0E518839494E893CACBD583C8C2A36028EB04E181",
          "signature": "13E29B3CF4DB1BF4CFCC52E9BD120AD3D35C61065F2953BA76745E10DCA014FA2B85F851EF8A073CA903DDE17E762517C5A6EE98E64898E8453261652532DB0C"
        }
      ]
    },
    {
      "signature": "F50DBE253695FBD1D565A29D858DCA12DBC8A40814F796792537D33C32C0A143E041DEB4F344701D67E872ADA5416F158563292888738C468C6590A3AA35130A",
      "signerPublicKey": "F0B829E77A702AA5BBA2E273ED2E08D44BE66529DC6E3B4118F4AA5D9AD04808",
      "version": 2,
      "network": 152,
      "type": 16705,
      "fee": "47200",
      "deadline": "66649225830",
      "transactionsHash": "A87EA83D7D775D4734D5892F2E4FD7FE975B06C5E5069612446D0C2E9D0E6E73",
      "transactions": [
        {
          "signerPublicKey": "F0B829E77A702AA5BBA2E273ED2E08D44BE66529DC6E3B4118F4AA5D9AD04808",
          "version": 1,
          "network": 152,
          "type": 16724,
          "recipientAddress": "988D15E5136B1C8C3281D390CBF8E5AB83CD564FAC32DCF1",
          "mosaics": [],
          "message": "0048656C6C6F2C206163636F756E7442"
        },
        {
          "signerPublicKey": "3E1D376049A25DC43C6392BF3D980BE9288CCD5F3C017BBD10B74070E80082CB",
          "version": 1,
          "network": 152,
          "type": 16724,
          "recipientAddress": "981797FA9D96B16786AA38F66C6DA7C06B9232442AAE031F",
          "mosaics": [],
          "message": "0048656C6C6F2C206163636F756E744121"
        }
      ],
      "cosignatures": [
        {
          "version": "0",
          "signerPublicKey": "3E1D376049A25DC43C6392BF3D980BE9288CCD5F3C017BBD10B74070E80082CB",
          "signature": "00E50CC87F4BAFB83646DDC8B4E5CEE5F810D824752E593B0F07351832B34F019A5C4511793F750E1FFB2B7C8271BEBFBF5E492FB0BF11F4D983773E8DAF3108"
        }
      ]
    }
  ]
}
socket close: 4
```

## ブロックデータの範囲取得

### ノードへリクエスト - ブロックデータの範囲取得

パケットタイプを`0ｘ008`にすると、範囲指定してブロックを取得出来ます。

ペイロードは以下の通りです。

- 開始ブロック高
- ブロック数
- 最大バイト数

最大バイト数を超えた場合、越えたブロックで打ち切ります。

```typescript:Catapult.ts
/** パケットタイプ */
private PacketType = {
  PULL_BLOCK: 0x0_04,
  CHAIN_STATISTICS: 0x0_05,
  PULL_BLOCKS: 0x0_08,
  PUSH_TRANSACTIONS: 0x0_09,
  PUSH_PARTIAL_TRANSACTIONS: 0x1_00,
  NODE_DISCOVERY_PULL_PING: 0x1_11,
  TIME_SYNC_NETWORK_TIME: 0x1_20,
  FINALIZATION_STATISTICS: 0x1_32,
  UNLOCKED_ACCOUNTS: 0x3_04,
}

async getBlocks(startHeight: bigint, count: number, maxSize: number) {
  const blocks: models.Block[] = []
  try {
    const payloadBuffer = new ArrayBuffer(16)
    const payloadDataView = new DataView(payloadBuffer)
    payloadDataView.setBigUint64(0, startHeight, true)
    payloadDataView.setInt32(8, count, true)
    payloadDataView.setInt32(12, maxSize, true)
    const socketData = await this.request(
      this.PacketType.PULL_BLOCKS,
      Buffer.from(payloadBuffer)
    )
    if (socketData) {
      let offset = 0
      do {
        const block = models.BlockFactory.deserialize(
          socketData.slice(offset)
        ) as models.Block
        blocks.push(block)
        offset += block.size
      } while (offset < socketData.length)
    }
  } catch (e) {
    if (e instanceof Error) console.error(e.message)
    else console.error(e)
  } finally {
    this.close()
  }
  return blocks
}
```

### レスポンスデータの解析 - ブロックデータの範囲取得

レスポンスデータの解析は、SDK の models にある BlockFactory クラスのデシリアライザを使用しています。

### メインの作成 - ブロックデータの範囲取得

実行するコードを作成します。

```typescript:src/mainPullBlocks.ts
import { Catapult } from './Catapult.js'

const catapult = new Catapult(
  'cert/ca.crt.pem',
  'cert/node.crt.pem',
  'cert/node.key.pem',
  '127.0.0.1'
)

const blocks = await catapult.getBlocks(1959301n, 3, 10240)
if (blocks) {
  for (const block of blocks) {
    console.log(JSON.stringify(block.toJson(), null, 2))
  }
}
```

### 実行 - ブロックデータの範囲取得

```posh
yarn tsx .\src\mainPullBlocks.ts
```

```plaintext
socket connected.
{
  "signature": "1697618C2F3CE2B7E2E1A9775AD572F19D4AA069AAE938A94099BC4212D271DD4F8120B1589BAC457D27FC52CF9D9A2C2035EAA71FFFE1EE884F0300FD2B820C",
  "signerPublicKey": "0340F9CA73A93F64CBCCE2E80B2E3F8AF195AAD6DC7B325E5C0A4DE103CDEBEB",
  "version": 1,
  "network": 152,
  "type": 33091,
  "height": "1959301",
  "timestamp": "66697909842",
  "difficulty": "10000000000000",
  "generationHashProof": {
    "gamma": "75194454D16BA9AC22B66F3366686663DAA43B499681C3EDB1A418075F372109",
    "verificationHash": "F3390EB7B89FFD95451EAB10F0EFFD69",
    "scalar": "FCC5BE4DBADCC692C681C5700E571A35BCAADB475170C524B630BB64F5885303"
  },
  "previousBlockHash": "3FD3C84C016F3CCAECCEA61EB3A73E15E053DF22FA9CE896EF550A18E753C8CB",
  "transactionsHash": "0000000000000000000000000000000000000000000000000000000000000000",
  "receiptsHash": "48B520A8D7BF73F375967954C452C2AE653651A260BAEF52D117558C4DADDCC0",
  "stateHash": "FE977512E16227F72E4D2A01D24D5B1F88F6BBEB5169A608169BEBFD86702FB6",
  "beneficiaryAddress": "981B6370BBD45899FA8450342741E92444359C3BE45060A1",
  "feeMultiplier": 0,
  "transactions": []
}
{
  "signature": "5EC54C34B9D29FB233A7C49588EFE0100F278686DD96ECBFC970416A53FF9089864E56677202B76CFA12F6175C540E6793938D1BF6E1FB48724971841B38C704",
  "signerPublicKey": "B8C83E30D74736E90D3318551998016446CF68C98D0932B688FD1463AAE6D125",
  "version": 1,
  "network": 152,
  "type": 33091,
  "height": "1959302",
  "timestamp": "66697943055",
  "difficulty": "10000000000000",
  "generationHashProof": {
    "gamma": "8F1223E615DF66A2368951B3CDF0844F10A1E8380F9C8D9E29EA09113147B423",
    "verificationHash": "CD35F76E5B5FA39309E5957E02581082",
    "scalar": "0E10109F40A49B486FC79F3962D6FF2A51283337102DC184E356EFB17A3F3F0C"
  },
  "previousBlockHash": "B32FFFB785FB598036AB9A71CDA25A0A2AD02FDF76CE477AF8BFA0277B8898FC",
  "transactionsHash": "0000000000000000000000000000000000000000000000000000000000000000",
  "receiptsHash": "5416BE359CBEB0E6EC06BB21F696A8D4D510EB0E80B3980BDEBCA1BBD4DA9ECD",
  "stateHash": "E387BED21A08FE5C2E56158B9CE76243708F1BD7E43EA3F35700B9D0E7EBE326",
  "beneficiaryAddress": "987CCA1A46DDD5D1C4341EA0332FEC10EAF05FA99E53A705",
  "feeMultiplier": 0,
  "transactions": []
}
{
  "signature": "9968D995869A0957FE1866AF59D4B55B4FEA16CD53022076C159D871EEA01F7CCFBB57819DC89BA70C0C9F987DAB4260968612173F3CE669D70336944BE38903",
  "signerPublicKey": "B8C83E30D74736E90D3318551998016446CF68C98D0932B688FD1463AAE6D125",
  "version": 1,
  "network": 152,
  "type": 33091,
  "height": "1959303",
  "timestamp": "66697978241",
  "difficulty": "10000000000000",
  "generationHashProof": {
    "gamma": "74F4CAAA1AC904CE9B8868C07549FEC5ABA35E18EC4553CB61EBCC6CA6356ACD",
    "verificationHash": "97EC11DEC30948DEA97C5ABCDE286CDC",
    "scalar": "B2565845887A6150A9BF261AC13B44F3BC9B75F90B6F16419357536F13884800"
  },
  "previousBlockHash": "8D30DBA16E9EE87097CDA20894F914023ADEA70B3A065D290CA9555D89084171",
  "transactionsHash": "0000000000000000000000000000000000000000000000000000000000000000",
  "receiptsHash": "5416BE359CBEB0E6EC06BB21F696A8D4D510EB0E80B3980BDEBCA1BBD4DA9ECD",
  "stateHash": "BBD845CA7149B3773EE0373F44D9C37026063D1DA5AA0D99DA341E116E07BEE8",
  "beneficiaryAddress": "987CCA1A46DDD5D1C4341EA0332FEC10EAF05FA99E53A705",
  "feeMultiplier": 0,
  "transactions": []
}
socket close: 8
```