Solidityの概要:データコントラクトの作成[パート1]

Solidityは、Ethereumプラットフォームでスマートコントラクトをコーディングするために使用される言語のようなJavaScriptです。イーサリアム仮想マシン(EVM)が理解できるバイトコード形式にコンパイルされます。これは強く型付けされた言語であり、カスタムデータ構造を定義する機能を備えています。 Solidityの概要パート1では、Solidity機能のサブセットを利用して、任意のドメインで機能するデータと基本ロジックを格納するコントラクトの完全なセットを作成するために再適用できるスマートコントラクトのテンプレートを作成する方法を説明します。これは、基本的な契約設計といくつかの関連する懸念事項をカバーするため、マルチパートシリーズになります.

Solidityの紹介

Solidityの概要:環境の作成

スマートコントラクトを実行するには、そのメソッドをコンパイル、デプロイ、および呼び出すことができるシステムが必要です。 3つすべてについて、非常にシンプルな統合ブラウザベースのアプリがあります ここに.

このツールを使用して、ライブイーサリアムノードに接続したり、モック環境を形成したりすることができます。この環境では、コントラクトメソッドでいくつかのテストケースを簡単に実行することもできます。インストールは不要で、完全にブラウザベースです。私はubuntuよりもchromeで使用しましたが、他のプラットフォームでも同様に機能すると確信しています。アプリの左側のペインには契約コードがあり、右側にはデプロイとテストのオプションがあります。アプリは、独自のシステムからの契約ファイルで動作することができます.

これから説明する契約のソースコードが利用可能です ここに. 契約コードの一部については、シリーズの後半で説明します。コードをダウンロードしてRemixにロードし、以下で説明するセクションを表示します。 Solidityの最新の未リリースバージョンは毎晩4.10であり、その特定のバージョンでサポートされている機能に依存します.

DataContract(基本的なデータ構造):

データ契約は標準的な用語ではありません。 Monax(初期のEris業界)のドキュメントで定義されているスマートコントラクトには複数のタイプ(パターン)があります。 「データ」タイプの契約は、データが追加、更新、削除、およびアクセスされる単純な概念です。データコントラクトを作成する過程で、すべてのコントラクトタイプのロールベースのセキュリティを管理するために使用できるアクセス制御リスト(ACL)コントラクト、データをログに記録して返すためのイベントメカニズム、およびその他のいくつかの機能を使用できるようになります。スマートコントラクト.

単純なデータコントラクトを作成するために、ユーザー定義の高レベルデータセットを想定します。お客様

単純化するために、個人であると想定する単純な顧客を構成します。

struct Customer {

uint id;

文字列名;

uint dateOfBirth;

uintソーシャル;

uintステータス;

}

データステータス

各データレコードにステータスがあることを前提として、構造体を実装しています。コレクション全体を削除して記録し、再配置することは不可能であるため、statusは、レコードの状態を定義するために利用する属性です。異なるドメインの契約は、異なるステータスのセットを持ちます。単純な仮定として、次の3つのステータスがあります(これは、顧客が検証を保留している、アクティブである、または削除されている可能性があるという考えによるものです)。

uint定数アクティブ= 1;

uint定数保留= 2;

uint定数が削除されました= 3;

ブロックチェーン上の参照データ型の削除されたレコードは完全に削除されるべきではないため、各レコードにステータスを割り当てることは適切な設計手法です。.

私たちの目的は、ブロックチェーン上のCustomer structインスタンスのコレクションを有効にし、特定の顧客、呼び出し顧客のリストにアクセスし、特定の顧客インスタンスを更新する機能を容易にすることです。これらの目的に関する横断的関心事は、アクセス制御戦略のログ記録と実装を可能にすることです。.

コレクションを作成するには、マッピング構造を活用します.

マッピング(uint => 顧客)顧客;

マッピング(uint => 顧客)顧客;

このマッピングは、キーがunsigned intであり、valueが顧客のインスタンスであるキー値のマップを作成する構造のようなマップのテンプレートです。このマッピングにはいくつかの制限があります。つまり、すべての値を取得するためにループする方法がありません。特定のgetロジックを介してのみ要素にアクセスできます。

顧客[キー];

このため、マッピング内の要素の数を維持し、その数に基づいて取得するために、シャドウキーを維持する必要があります。.

public uint count = 0;

これで、顧客データを格納するために使用するデータ構造の準備が整いました。.

データ契約(データ作成):

顧客インスタンスを作成してキーオフするために、構成データを受け入れるメソッドを実装します.

function create Customer(uint id、string name、uint dateOfBirth、uint social){

Customers [count] = Customer(id、name、dateOfBirth、social、pending);

count ++;

}

上記の方法は、マッピングにデータを追加し、シャドウキーの数を増やします。注意すべきことは、同じシャドウキーを使用してデータをキーオフしていることです。.

データにランダムにアクセスするには、データをキーオフした特定のキーを指定する必要があります.

関数getCustomer(uint index)

定数が返されます(uint id、文字列名、uint dateOfBirth、uint social、uint status)

{{

id = Customers [index] .id;

name = Customers [index] .name;

dateOfBirth = Customers [index] .dateOfBirth;

social = Customers [index] .social;

status = Customers [index] .status;

}

この方法は、契約データの状態を変更しないため、一定の方法です(読み取り専用の方法です)。したがって、このメソッドを呼び出すためにガスは必要ありません.

すべての顧客にアクセスするには、カウントシャドウキーを活用する必要があります。クライアントにループ構造を実装し、上記のインデックスベースの呼び出しを再利用する必要があります。契約クライアントの説明を説明します.

構造体の特定の属性に基づいて顧客にアクセスするには、ループベースのブルート検索を実装する必要があります。そのデータの作成を担当したトランザクションの解析を使用してそれを読み取るためのより効率的な方法があります.

関数getCustomerById(uint id)

定数が返されます(uint idRet、文字列名、uint dateOfBirth、uint social、uint status)

{{

for(var i = 0; i<カウント; i ++)

{{

if(customers [i] .id == id){

idRet = Customers [i] .id;

name = Customers [i] .name;

dateOfBirth = Customers [i] .dateOfBirth;

social = Customers [i] .social;

status = Customers [i] .status;

戻る;

}

}

}

これは、属性値から顧客を取得するための非常に非効率的な方法です。この方法には、非効率性以外にも他の問題があります。文字列を完全に一致させることは簡単にできないため、文字列属性を一致させることはできません。また、最初の一致を返します。一致のリストを返すことはできません。このシリーズの後半では、このデータにアクセスするためのより効率的な方法について説明します。.

データ契約(データ更新):

データの更新方法は、アクセス方法の逆です。覚えておくべき唯一のことは、このメソッドはブロックチェーン状態の変更をもたらすため、トランザクションが確認された後にのみ変更が反映されることです。シリーズの後半で、データにアクセスする前にトランザクションが確認されていることを確認する方法について説明します。.

function updateCustomer(uint index、string name){

Customers [index] .name = name;

}

インデックス値をチェックするのは理にかなっています(カウントよりも小さい必要があります)

function updateCustomer(uint index、string name){

if(インデックス >カウント)スロー;

Customers [index] .name = name;

}

function updateCustomerStatus(uint index、uint status){

if(インデックス >カウント)スロー;

Customers [index] .status = status;

}

各属性を更新するには、異なるメソッドを実装する必要があります。ここでは、名前を更新しています。メソッドupdateCustomerStatus()は、レコードを有効または無効にできる特別なメソッドとして扱う必要があります.

インデックスキーにアクセスするアクセス方法に同じチェックを追加することは可能ですが、無効なインデックスが指定された場合は戻り値がnullになるため、クライアントは応答を検証して適切なエラーを返すことができるはずです。アクセスはより頻繁に呼び出されるメソッドセットになるため、可能な限り効率的にする必要があります.

契約のテスト:

契約をテストするには、右側のパネルの[環境]タブ(ボックスアイコン)に移動します.

右側にリストされている契約が表示され、アドレスを提供するオプション(住所)と作成するオプションがあります。 javascript VMラジオボタンを選択します(デフォルトで選択され、作成を押します)。これにより、コントラクトのテストを実行してイベントをデバッグするためのローカルのブラウザー内環境が作成されます。.

Solidityの概要:データコントラクトの作成[パート1]

Solidityの概要:データコントラクトの作成[パート1]

このテスト環境では、コントラクトメソッドを個別に呼び出して、データの結果を確認できます。.

まず、create Contractメソッドを呼び出して、ブロックチェーンにデータを追加しましょう(実際のデータではありませんが、モックです)。.

メソッド呼び出しcreateCustomerで赤いマークの付いたボタンを探し、JavaScriptクライアントを介してこのメ​​ソッドを呼び出す場合と同様に、コンマで区切ってその横のテキストフィールドにパラメーターを追加します。例: (簡単にするために、dateOfBirthを、ユニットに収まるユニットタイムスタンプにするように選択しました)

例: (簡単にするために、dateOfBirthを、ユニットに収まるユニットタイムスタンプにするように選択しました)

101, "ジャック", 845078400、1234567

このパラメータを設定して、[顧客の作成]をクリックすると、通話の下に次のように印刷されます。

結果: "0x"

取引費用:129390ガス.

実行コスト:106454ガス.

これは、メソッド呼び出しが成功したことを示します。カウントボタン(メソッド呼び出しcount())を押して顧客の数を確認することで確認できます。 Solidityは、署名member()を使用した直接呼び出しを通じて、パブリックメンバーを公開することを忘れないでください。.

呼び出しは次のように出力されます。

"0x0000000000000000000000000000000000000000000000000000000000000002"

取引費用:21505ガス。 (警告)

実行コスト:233ガス.

デコード:

uint256:1

このuint256の値は1で、レコードセットに単一のメンバーがあることを示します。.

上記のcreateCustomer呼び出しを複数回実行して、結果を確認できます。重複レコードの追加はチェックされないことに注意してください。これはクライアントがチェックする必要があります.

インデックスベースのgetCustomer(0)を使用して顧客を取得できます–インデックスは0で始まることに注意してください。次のような出力が表示されます。

値:

"0x000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000325edf80000000000000000000000000000000000000000000000000000000000012d687000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000044a61636b000000000000000000000000000000000000000000000000000000000000"

取引費用:23404ガス。 (警告)

実行コスト:2004ガス.

デコード:

uint256 id:101

文字列名:ジャック

uint256 dateOfBirth:845078400

uint256ソーシャル:1234567

uint256ステータス:2

返される値は、返されるエンコードされたデータです。デコードされて表示され、パラメータ値は以下の順序で表示されます.

これで、いくつかのテストデータに対してテストされた完全な作業契約ができました。.

コントラクトが期待どおりに機能しない場合があります。その場合、メソッドの実行時にコントラクトデータの状態を確認して問題を特定するには、コントラクトをデバッグする必要があります。現在、Solidityデバッガーはありません。この機能を備えたSolidityIDE – Mixがありますが、現在はサポートされていません。あなたはあなた自身の責任でそれをテストすることができます.

次に、コントラクトを実際のイーサリアムインスタンスにデプロイし、単純なjavascriptクライアントを使用して呼び出します。.

契約の展開:

パリティを使用してローカルイーサリアムノードを設定する方法については、以前の記事を参照してください。この機能を使用し、8545でJSON_RPCポートを公開するローカルで実行されているイーサリアムインスタンスがあることを前提としています。また、アカウントが作成され、accounts [0]の場所に返されることを前提としています。また、このアカウントには、契約を展開し、ガス料金でトランザクション呼び出しを実行します.

リミックスIDEを使用すると、このコントラクトをIDEからイーサリアムインスタンスに直接デプロイできます。これを行うには、最初に[環境]タブからWeb3プロバイダーオプションを選択する必要があります。環境が現在ピックアップされている場合、契約の下にエラーは表示されません.

Screen_3(コントラクトデプロイオプション)

Solidityの概要:データコントラクトの作成[パート1]

IDEは、コントラクトのコンパイルプロセスから3つの出力を提供しますが、コントラクトは自動的にコンパイルされます。画面_3に示すオプションが表示されていることを確認します。それ以外の場合は、コンパイルが失敗したことを意味し、コンパイルエラーが表示されるはずです.

バイトコードは、コードのコンパイル時に作成されるEVMコードです。これは、イーサリアムが理解できる低レベルの命令セットです。 2つ目は、アプリケーションバイナリインターフェイスまたはコントラクトコードのABIです。 ABIは、定義されたJSON形式でのコントラクトのメソッド署名、戻り値の型、メンバーなどの単なるリストです。このABIは、実際のjavascriptクライアントからコントラクトを呼び出すときに必要です。.

3番目のオプションWeb3デプロイは、コントラクトをノードインスタンスに直接プッシュできるオプションです。このオプションを選択するだけで、ブロックチェーン上の契約アドレスが返されます。(sreen_2のように)。この契約アドレスは、まもなく作成するjavascriptクライアントで必要になるため重要です。イーサリアムコンソールからブロックチェーンにコントラクトを直接デプロイできない場合。 web3デプロイオプションに対してテキスト領域のスクリプトをコピーして、コンソールに貼り付けるだけです。 「contractmined」の後にチェーン上のアドレスが続くトーンconsole.log出力が表示されます。.

実際のクライアントから契約を実行する.

契約をエンタープライズアプリケーションコードと統合するため。これを行うには、ブラウザで実行できる単純なjavascript / htmlクライアントを作成します。このクライアントをnodejsアプリケーションとして実行することもできます。これは、シリーズの後半で取り上げる内容です。.

イーサリアムブロックチェーンと通信するために、イーサリアムは低レベルを公開します JSON-RPC インターフェース。このインターフェースは、契約へのトランザクションを受け入れます。これは非常に低レベルのインターフェースであるため、直接操作するのは困難です。 javascriptフレームワークがあります web3.js これにより、より高いレベルの契約コードの抽象化が可能になり、アプリケーションを契約呼び出しと統合できるようになります.

ブラウザでサポートされている環境でweb3を有効にするには、コントラクトと対話するためにページコード内で単一のスクリプトファイルを参照する必要があります.

Web3.jsは、上記のドキュメントのリンクからダウンロードできます。 Web3は、イーサリアムでインスタンスを契約するためのハンドルを生成して、Solidityソースに実装したすべてのメソッド呼び出しを有効にします。これらのメソッド呼び出しは、メソッドスクリプトへの直接のJavaScript参照があるかのようにコーディングできます。これはJSON-RPCインターフェースによって有効になります.

コントラクトハンドルを取得するために利用できるテンプレート化されたアプローチがあります。最初に必要なことは、web3をインスタンス化し、コントラクトABIをそれに供給することです。.

var Web3 = require( ‘web3’);

var web3 = new Web3();

web3.setProvider(“<スパンlang ="zxx"><a href ="http:// localhost:8545 /">http:// localhost:8545a>スパン>”);

web3.eth.defaultAccount = web3.eth.accounts [0];

プロバイダーのURLは、ローカルのJSON_RPCインターフェースです。デフォルトのアカウント設定は、契約でトランザクションを実行するときにアカウントからのとして使用されるイーサリアムウォレットです。 gethノードインスタンスを使用している場合は、アカウントがロック解除されていることを確認する必要があります。デフォルトでは、アカウントはロック解除されてから30秒ごとにロックされます。.

次のステップは、契約ABIを提供することにより、契約ブループリントをインスタンス化することです。.

var customerContract = web3.eth.contract([ABI JSON]).

ABI JSON配列は通常長いJSON文字列であるため、言い換えるだけですが、screen3に示すように、インターフェイステキスト領域からABI配列全体をコピーする必要があります。顧客契約の青写真を入手したら、契約がブロックチェーン上に存在する実際のアドレスを提供することにより、それをインスタンス化する必要があります.

var customerContractObject = customerContract.at( ‘0x76bd9986c5c3e00111c82e16e01e282696d2b3fb’);

このアドレスは、web3デプロイまたはイーサリアムコンソールからコントラクトをデプロイしたときに取得したものになります。コントラクトハンドルをデプロイメントアドレスにリンクしておくと、そのアドレスにトランザクションを送信することでコントラクトメソッドを実行できます。たとえば、htmlフォームがユーザーからのフォーム値の入力を受け入れた後に顧客レコードを追加するとします。その場合、html + web3コードは次のようになります。

<html>

<頭>

<link rel =” stylesheet” type =” text / css” href =” style.css”>

<スクリプトタイプ=” text / javascript” src =” / usr / local / lib / node_modules / web3 / dist / web3.js”><スクリプトtype =” text / javascript” src =” jquery.js”>脚本>

<スクリプトタイプ=” text / javascript”>

var Web3 = require( ‘web3’);

var web3 = new Web3();

web3.setProvider(new web3.providers.HttpProvider()); //これはデフォルトです– localhost:8545

web3.eth.defaultAccount = web3.eth.accounts [0];

var customerContract = web3.eth.contract([ABI JSON]);

var customerContractObject = customerContract.at( ‘0x76bd9986c5c3e00111c82e16e01e282696d2b3fb’);

関数レジスタ(){

var txn = customerContractObject.createCustomer($( ‘id’)。val()、$( ‘name’)。val()、$( ‘dob’)。val()、$( ‘social’)。val() 、{gas:144840});

console.log(txn);

}

脚本>

頭>

<体>

<input type =” number” name =” id” id =” id” placeholder =” Customer Id” />

<input type =” text” name =” name” id =” name” placeholder =” Customer Name” />

<input type =” date” name =” dob” id =” dob” placeholder =” Customer Date Of Birth” />

<input type =” number” name =” social” id =” social” placeholder =” Customer Social Security Number” />

<input type =” button” value =” Register” onclick =” register();” />

体>

html>

上記のコードは、web3.jsとjqueryへのパスを修正すると、すぐに機能します。コントラクトハンドルでメソッドを呼び出したのと同じように:

var txn = customerContractObject.createCustomer($( ‘id’)。val()、$( ‘name’)。val()、$( ‘dob’)。val()、$( ‘social’)。val() 、{gas:144840});

他のすべてのメソッドを呼び出すことができます。推定ガスは、テストメソッドの呼び出しから入力する必要があります。これは私の構成では144840です。上記の呼び出しは、このメソッドを実行するためにブロックチェーン上に作成されたトランザクションのトランザクションIDを返します。このトランザクションはブロックチェーンの一部になり、この顧客がいつ、どのように、誰によって作成されたかを監査したいときにいつでも参照できます。.

コントラクトのコーディング中に見たように、呼び出しには2つのタイプがあります。 createCustomer、updateCustomerなどのコントラクトの状態を更新するもの。読み取り専用で定数としてマークされているもの。前者は常にトランザクションIDハッシュを返します。トランザクションIDハッシュは、トランザクションを参照するために使用できるトランザクションの64バイトのIDです。ここで行っているように、同期的にコントラクトを実行している場合。後者は、コンマ区切りの配列で求められる実際の値を返します。例:呼び出し:

var customer = customerContractObject.getCustomer($( ‘index’)。val());

console.log(顧客)

このような値の配列をログに記録します-101, "ジャック", 845078400、1234567

シリーズの次のパートでは、アクセス制御、イベントログ、契約の削除など、機能以外の懸念事項や側面が契約にどのように組み込まれているかを確認します。これらの問題を具体的に扱う契約の一部について説明します.

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me