LoginSignup
6
2

More than 1 year has passed since last update.

Amazon Managed Blockchain を構築してみた (Ethereum)

Last updated at Posted at 2022-05-05

はじめに

Amazon Managed Blockchain サービスは、Ethereum や Hyperledger Fabric を構成してくれるマネージドサービスです。自分たちで EC2 で構成する時と比べて、数クリックで Node を含めた環境が出来上がるので、自分たちのアプリケーションに時間を費やすことができます。

前の記事では、Hyperledger Fabric を触ってみる内容でした。今回の記事では、Ethereum を触ってみる内容になっています。Ethereum 自体を深く理解できていないので、Ethereum 自体の勉強も兼ねています。

次の URL を参考に進めています。

Ethereum Node 作成

まず、Amazon Managed Blockchain のサービスページに移動して、Join public network を選択します。

image-20220504115148144.png

4 つのネットワークから選択できます。今回はテスト用なので、Goerli を選んでみます。AWS Document に、Goerli テスト用途としておすすめと書かれていたので、これを選びます。Mainnet は、実際にお金が掛かる本番用ネットワークなので、動作確認は Testnet を利用すると良いです。

URL : https://docs.aws.amazon.com/ja_jp/managed-blockchain/latest/ethereum-dev/ethereum-nodes.html

image-20220504115655923.png

Ethereum node をどのように構成するのか選択して、Create node を押します

image-20220504115835167.png

Creating になります。30 分くらいかかると表示されたので、それくらい待ちます。Create node を選択することで他の AZ に Node を構成できます。これにより高可用性が実現できます。

image-20220504115901036.png

一定時間後、Available になりました。詳細画面を見てみます。

image-20220504134630102.png

Node には、2つの Endpoint があります。後ほど利用するので、メモをしておきましょう。

  • WebSocket
  • HTTP

image-20220504134948366.png

アプリケーションから Ethereum Node の API を呼びだす

Ethereum Node が作成できたので、アプリケーションから API を呼びだしてみます。

Web3.jsは、Nodeパッケージマネージャ (npm) で利用可能な JavaScript ライブラリです。以下の例を実行すると、Node.js 用の Javascript ファイルを使用して、Ethereum に JSON-RPC API 呼び出しを送信することができます。この例では、Ethereum ノードへの HTTP 接続と WebSocket 接続を行います。

EC2 インスタンス上で、Ethereum Node にアクセスする構成を確認します。構成図でみるとこんな感じです。Amazon Managed Blockchain サービスを使って、Goerli ネットワークに参加している Ethereum Full Node を作成しました。この Node はエンドポイントを持っているので、EC2 インスタンスの Node.js アプリから API を実行してみます。

image-20220505145036358.png

EC2 インスタンスにインストールされている Node のバージョンを確認します。存在しない場合はインストールをしてください。

> node --version
v16.13.0

必要なパッケージをインストールします。

npm install aws-sdk web3 xhr2

EC2 インスタンスの Amazon Linun2 の環境変数を指定します。環境に合わせて、アクセスキーや Endpoint の名前を変更していきましょう。

export AWS_ACCESS_KEY_ID="xxxxxx"
export AWS_SECRET_ACCESS_KEY="yyyyyy"
export AWS_DEFAULT_REGION="ap-northeast-1"
export AMB_HTTP_ENDPOINT="https://nd-76uz24bmarcszofd6lvqm22eea.ethereum.managedblockchain.ap-northeast-1.amazonaws.com"
export AMB_WS_ENDPOINT="wss://nd-76uz24bmarcszofd6lvqm22eea.wss.ethereum.managedblockchain.ap-northeast-1.amazonaws.com"

適当なディレクトリに移動します

cd ~/temp/blockchain-ethereum/

以下のファイルを作成します

aws-http-provider.mjs
/////////////////////////////////////////////////////
// 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);
    }
  }
}

同じフォルダに次のファイルを作成します。このファイルは、Ethereum Node に対して、getNodeInfo API を呼びだすものになっています。

web3-example-http.mjs
import Web3 from 'web3';
import AWSHttpProvider from './aws-http-provider.mjs';
const endpoint = process.env.AMB_HTTP_ENDPOINT
const web3 = new Web3(new AWSHttpProvider(endpoint));
web3.eth.getNodeInfo().then(console.log);

動作確認です。以下のコマンドで、EC2 インスタンス上にある Node から、Amazon Managed Blockchain の Ethereum Node に接続します。Geth/v1.10.16-stable/linux-amd64/go1.17.5 みたいな文字が表示されていれば正常です。

> node web3-example-http.mjs
Geth/v1.10.16-stable/linux-amd64/go1.17.5

Ethereum Node でアカウントを作成

Amazon Managed Blockchain で作成した Ethereum Node を使って、テストネットワーク上でのアカウントを作成してみましょう。以下のファイルを作成します。web3.eth.accounts.create(); と呼び出しており、アカウント作成を実行しているプログラムです。

web3-create-account.mjs
import Web3 from "web3";
import AWSHttpProvider from "./aws-http-provider.mjs";
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);

実行結果です。作成したアカウントの address が表示されます。作成したアカウントの ID みたいなものなので、メモっておくと良いです。

> node web3-create-account.mjs
{
  address: '0x9cf240b6b81C05507cF3BD5D4fe9de4f1BB98142',
  privateKey: '0x111111111111111111111111111',
  signTransaction: [Function: signTransaction],
  sign: [Function: sign],
  encrypt: [Function: encrypt]
}

MetaMask で Goerli に接続

Amazon Managed Block の外から、Georli ネットワークに対するリクエストを通じて、テストネットワークとしての動作をみていきましょう。システム構成図的にはこんな感じです。MetaMask からの接続先は、Ethereum Node は意識しておらず、あくまで Georli ネットワークに対してのリクエストになっています。

image-20220505150148532.png

MetaMask は、Ethereum を用いる分散型アプリケーション(DApps)にアクセスしやすくするためのソフトウェアです。ブラウザ拡張機能版とモバイルアプリ版があり、Chrome の拡張を利用して、テストネットである Goerli にアクセスしてみます。

開始を押す

image-20220505131103522.png

ウォレットを作成

image-20220505131137865.png

同意する

image-20220505131200990.png

設定

image-20220505131804379.png

高度な設定

image-20220505131829712.png

テストネットワークを表示

image-20220505131904331.png

Goerli テストネットワークを指定

image-20220505131941257.png

Goerli で GOETH の取得

MetaMask としてのアカウントを持っています。Ethereum Node 上で API を呼びだして作成したアカウントとは別物です。作成直後で、ETH を持っていないので、取得するためにアドレスをコピーしておきましょう。

image-20220505132157854.png

次の URL にアクセスしてリクエストを投げると、ETH を取得できます。

MetaMask のアカウントのアドレスを入力して、Send Me ETH を押します。

image-20220505133909584.png

Metamask 上の自分のアカウントに、0.05 ETH が追加されていることがわかります。

image-20220505134005175.png

Ethereum Node で作成した Account に送金

MetaMask の持っているアカウントから、Ethereum Node で作成した Account に送金をしてみます。

image-20220505134903561.png

Ethereum Node で作成した Account の Address を指定して、送金金額を指定します。0.001 ETH を送ってみます。

image-20220505135017781.png

Ethereum では、送金などのトランザクションで GAS 代が掛かります。今回はテストネットなので実際にはお金は掛かっていません。このまま確認を押します。

image-20220505135109617.png

送金されました。

image-20220505135148062.png

Amazon Managed Blockchain の Ethereum Node 上で、送金された ETH を getBalance API で確認してみます。Node.js のファイルを作成します。

web3-get-balance.mjs

account は自分のアカウントの address を指定します。

import Web3 from "web3";
import AWSHttpProvider from "./aws-http-provider.mjs";
const endpoint = process.env.AMB_HTTP_ENDPOINT;
const web3 = new Web3(new AWSHttpProvider(endpoint));
web3.eth.getNodeInfo().then(console.log);

// get balance
const account = "0x9cf240b6b81C05507cF3BD5D4fe9de4f1BB98142";
web3.eth.getBalance(account).then(console.log);

実行例です。単位は異なりますが、0.001 ETH が送られてきていることがわかります。

> node web3-get-balance.mjs
1000000000000000

検証を通じてわかったこと

参考URL

AWS Document
https://docs.aws.amazon.com/ja_jp/managed-blockchain/latest/ethereum-dev/managed-blockchain-ethereum-overview.html

Ethereum 入門
https://book.ethereum-jp.net/

Ethereum Network Stats
https://ethstats.net/

ブロックチェーンEthereum入門 3
https://www.intellilink.co.jp/column/fintech/2016/061700.aspx

AWSではじめるブロックチェーン Amazon Managed Blockchain
https://dev.classmethod.jp/articles/amb-tutorial/

自宅サバで作る! イーサリアム 2.0 TestnetのValidatorノード(Prysm版)~資産の減少を防ぐにはどう運用管理する?
https://internet.watch.impress.co.jp/docs/column/shimizu/1319649.html

意外と簡単?Ethereum Blockchain アプリのローカル開発手順。
https://blog.vivita.io/entry/2018/08/06/070000

スマホさえあれば自由に使える!イーサリウムでブロックチェーンを体験する方法
https://dime.jp/genre/989928/

Learn to Code Blockchain DApps By Building Simple Games
https://cryptozombies.io/

「早起きは0.003ETHの得」ってほんと!?→ほんとです
https://qiita.com/Shoyu_N/items/b765344bae9305f29c76

web3.jsでデプロイしたコントラクトをReactで使う(前編)
https://zenn.dev/shunp110/articles/630a0166f468e4

Deploy NFT on Ethereum using Amazon Managed Blockchain
https://github.com/aws-samples/nft-deployment-amazon-managed-blockchain

Simple NFT Marketplace (日本語のドキュメントもあり)
https://github.com/aws-samples/simple-nft-marketplace

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2