AWSではじめるブロックチェーン Amazon Managed Blockchain

2022.01.24

MAD事業部の新井です。

今回はこちらのドキュメントをベースにAmazon Managed Blockchainを触っていこうと思います。

操作自体はとても簡単です。

ノードを立てる

Amazon Managed Blockchainではフルマネージドサービスなブロックチェーンのノードを簡単に構築できます。

ノードはPublicとPrivate の2つから選べます。

PublicはEthereum、PrivateはHyperledger Fabricのプラットフォームになります。

Publicは既に存在するEthereumネットワークへ参加できます。一方、Privateでは、独立したネットワークを構築できす。

今回はPublicを利用します。

利用するネットワークは、MainnetTestnet:RinkebyTestnet:Ropstenのいずれかから選択できます。 今回は、テストネットとして比較的利用しやすいRopstenを選びます。

ノードはGethをベースに作成されます。

しばらくするとノードが立ち上がるので、それまで待ちます。

Mainnetを選択する場合は、ノードの作成に1時間以上かかることもあるので注意が必要です。

接続してみる

準備

  • pre-install

npm install aws-sdk web3 xhr2

  • setup envs
export AWS_ACCESS_KEY_ID="<aws-access-key-id>"
export AWS_SECRET_ACCESS_KEY="<aws-secret-access-key>"
export AWS_DEFAULT_REGION="<aws-default-region>"
export AMB_HTTP_ENDPOINT="https://<amb-http-endpoint>"
export AMB_WS_ENDPOINT="wss://<amb-websocket-endpoint>"

web3js over HTTPでAmazon Managed Blockchainのノードに接続

  • code: aws-http-provider.js
/////////////////////////////////////////////////////
// Authored by Carl Youngblood
// Senior Blockchain Solutions Architect, AWS
// Adapted from web3 npm package v1.3.0
// licensed under GNU Lesser General Public License
// https://github.com/ethereum/web3.js
/////////////////////////////////////////////////////

import AWS from 'aws-sdk';
import HttpProvider from 'web3-providers-http';
import XHR2 from 'xhr2';

export default class AWSHttpProvider extends HttpProvider {
  send(payload, callback) {
    const self = this;
    const request = new XHR2(); // eslint-disable-line

    request.timeout = self.timeout;
    request.open('POST', self.host, true);
    request.setRequestHeader('Content-Type', 'application/json');

    request.onreadystatechange = () => {
      if (request.readyState === 4 && request.timeout !== 1) {
        let result = request.responseText; // eslint-disable-line
        let error = null; // eslint-disable-line

        try {
          result = JSON.parse(result);
        } catch (jsonError) {
          let message;
          if (!!result && !!result.error && !!result.error.message) {
            message = `[aws-ethjs-provider-http] ${result.error.message}`;
          } else  {
            message = `[aws-ethjs-provider-http] Invalid JSON RPC response from host provider ${self.host}: ` +
              `${JSON.stringify(result, null, 2)}`;
          }
          error = new Error(message);
        }

        callback(error, result);
      }
    };

    request.ontimeout = () => {
      callback(`[aws-ethjs-provider-http] CONNECTION TIMEOUT: http request timeout after ${self.timeout} ` +
        `ms. (i.e. your connect has timed out for whatever reason, check your provider).`, null);
    };

    try {
      const strPayload = JSON.stringify(payload);
      const region = process.env.AWS_DEFAULT_REGION || 'us-east-1';
      const credentials = new AWS.EnvironmentCredentials('AWS');
      const endpoint = new AWS.Endpoint(self.host);
      const req = new AWS.HttpRequest(endpoint, region);
      req.method = request._method;
      req.body = strPayload;
      req.headers['host'] = request._url.host;
      const signer = new AWS.Signers.V4(req, 'managedblockchain');
      signer.addAuthorization(credentials, new Date());
      request.setRequestHeader('Authorization', req.headers['Authorization']);
      request.setRequestHeader('X-Amz-Date', req.headers['X-Amz-Date']);
      request.send(strPayload);
    } catch (error) {
      callback(`[aws-ethjs-provider-http] CONNECTION ERROR: Couldn't connect to node '${self.host}': ` +
        `${JSON.stringify(error, null, 2)}`, null);
    }
  }
}
  • code: web3-example-http.js
import Web3 from "web3";
import AWSHttpProvider from "./aws-http-provider.js";
const endpoint = process.env.AMB_HTTP_ENDPOINT;
const web3 = new Web3(new AWSHttpProvider(endpoint));
web3.eth.getNodeInfo().then(console.log);
  • 接続確認
$ node web3-example-http.js

Geth/v1.10.12-stable/linux-amd64/go1.16.7

Gethベースのノードが構築されているのが確認できます。

ETHを送金してみる

ここからは、ドキュメント外の内容になります。

MetamaskのアカウントからAmazon Managed Blockchainで作成したアカウントへ送金してみようと思います。

Amazon Managed Blockchainでアカウントを作成

まずはAmazon Managed Blockchainでアカウントを作成します。

新しく下記のファイルを作成します。

  • code: web3-create-account.js
import Web3 from "web3";
import AWSHttpProvider from "./aws-http-provider.js";
const endpoint = process.env.AMB_HTTP_ENDPOINT;
const web3 = new Web3(new AWSHttpProvider(endpoint));
web3.eth.getNodeInfo().then(console.log);

// create account
const account = web3.eth.accounts.create();
console.log(account);
  • 実行

アドレスが出力されるので、控えておきます。

$ node web3-create-account.js
{
  address: '0x54A2e37C1CBeAFB9fA46092C9b946F89a5c7AA3f',
  privateKey: '<your-private-key>',
  signTransaction: [Function: signTransaction],
  sign: [Function: sign],
  encrypt: [Function: encrypt]
}

Metamaskでテストネットに接続

MetamaskのChrome Extensionを利用します。

  • テストネットに接続

Ropsten FaucetでETHを取得

RopstenではFaucetと呼ばれるアカウントからETHを取得できます。

Googleで「Ropsten Ethereum」と検索すれば、ETHを送金してくれるサイトやGitterなどが見つかります。

MetamaskのFaucetを利用したかったのですが、稼働していなかったので、こちらのサイトから自分のアドレスを入力して送金してもらいました。

Metamask上の自分のアドレスは下記の様にクリップボードにコピーできます。

MetamaskでETHを送金

Faucetからの入金を確認できたら、次にMetamaskのアドレスからAMBのアドレスへ送金します。

送信先のアドレスを入力し、今回は0.1ETHを送金したいと思います。

ちなみにトランザクションのIDが分かれば、こちらのサイトから送金状況も確認できます。

Amazon Managed Blockchainで入金確認

  • code: web3-get-balance.js
import Web3 from "web3";
import AWSHttpProvider from "./aws-http-provider.js";
const endpoint = process.env.AMB_HTTP_ENDPOINT;
const web3 = new Web3(new AWSHttpProvider(endpoint));
web3.eth.getNodeInfo().then(console.log);

// get balance
const account = "0x54A2e37C1CBeAFB9fA46092C9b946F89a5c7AA3f";
web3.eth.getBalance(account).then(console.log);
  • 実行

単位は異なりますが、金額が増えているのが確認できると思います。

$ node web3-get-balance.js

Geth/v1.10.12-stable/linux-amd64/go1.16.7
100000000000000000

まとめ

いかがだったでしょうか。

なんとなくですが、Amazon Managed Blockchainで実現できることが分かった気がします。

次は、アプリケーションにどのように組み込むか?というのをトライしてみたいと思います。