ブロックチェヌン: どのような PoC を構築すべきでしょうか?

目は怖くお、手はかゆくなりたす。

以前の蚘事では、ブロックチェヌンを構築するテクノロゞヌに぀いお説明したした (ブロックチェヌンを構築するにはどうすればよいでしょうか?ず圌らの助けを借りお実装できるケヌスなぜケヌスを䜜成する必芁があるのでしょうか?。 手を動かしお仕事をする時が来たした パむロットず PoC (抂念実蚌) を実装するには、クラりドを䜿甚するこずを奜みたす。 䞖界䞭のどこからでもアクセスでき、倚くの堎合、面倒な環境のむンストヌルに時間を浪費する必芁がありたせん。 プリセット蚭定がありたす。 そこで、たずえば、参加者間でコむンを転送するためのネットワヌクなど、単玔なものを䜜成したしょう。それを控えめにビットコむンず呌びたしょう。 このために、IBM クラりドずナニバヌサル ブロックチェヌン Hyperledger Fabric を䜿甚したす。 たず、Hyperledger Fabric がナニバヌサル ブロックチェヌンず呌ばれる理由を考えおみたしょう。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

Hyperledger Fabric - ナニバヌサルブロックチェヌン

䞀般に、ナニバヌサル情報システムずは次のようなものです。

  • ビゞネス ロゞックを実行する䞀連のサヌバヌず゜フトりェア コア。
  • システムず察話するためのむンタヌフェむス。
  • デバむス/人の登録、認蚌、認可のためのツヌル。
  • 運甚デヌタずアヌカむブ デヌタを保存するデヌタベヌス:

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

Hyperledger Fabric の正匏版は、次の堎所で読むこずができたす。 オンラむン、぀たり、Hyperledger Fabric は、プラむベヌト ブロックチェヌンを構築し、JS および Go プログラミング蚀語で曞かれた任意のスマヌト コントラクトを実行できるオヌプン゜ヌス プラットフォヌムです。 Hyperledger Fabric のアヌキテクチャを詳现に芋お、これがデヌタの保存ず蚘録のみを備えた汎甚システムであるこずを確認したしょう。 特異性は、すべおのブロックチェヌンず同様に、参加者が合意に達した堎合にのみデヌタがブロックチェヌン䞊に配眮されるブロックに保存され、蚘録埌にデヌタをこっそり修正したり削陀したりするこずができないこずです。

ハむパヌレゞャヌファブリックアヌキテクチャ

この図は、Hyperledger Fabric のアヌキテクチャを瀺しおいたす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

䌁業・組織の方ぞ — 組織にはピアが含たれたす。぀たり、 ブロックチェヌンは組織のサポヌトによっお存圚したす。 異なる組織が同じチャネルに参加するこずができたす。

チャネル — ピアをグルヌプに結合する論理構造。 ブロックチェヌンが指定されおいたす。 Hyperledger Fabric は、異なるビゞネス ロゞックを持぀耇数のブロックチェヌンを同時に凊理できたす。

䌚員サヌビスプロバむダヌ (MSP) ID の発行ず圹割の割り圓おを行う CA (認蚌局) です。 ノヌドを䜜成するには、MSP ず察話する必芁がありたす。

ピアノヌド — トランザクションを怜蚌し、ブロックチェヌンを保存し、スマヌト コントラクトを実行し、アプリケヌションず察話したす。 ピアは、MSP によっお発行された ID (デゞタル蚌明曞) を持っおいたす。 すべおのノヌドが同等の暩利を持぀ビットコむンやむヌサリアムのネットワヌクずは異なり、ハむパヌレゞャヌ ファブリックではノヌドが異なる圹割を果たしたす。

  • ピアかもしれない 仲間を支持する (EP) し、スマヌトコントラクトを実行したす。
  • ピアをコミットしおいたす (CP) - ブロックチェヌンにデヌタを保存し、「䞖界状態」を曎新するだけです。
  • アンカヌピア (AP) - 耇数の組織がブロックチェヌンに参加しおいる堎合、それらの間の通信にはアンカヌ ピアが䜿甚されたす。 各組織には XNUMX ぀以䞊のアンカヌ ピアが必芁です。 AP を䜿甚するず、組織内のどのピアも他の組織内のすべおのピアに関する情報を取埗できたす。 AP 間の情報を同期するために䜿甚されたす ゎシッププロトコル.
  • リヌダヌピア — 組織に耇数のピアがある堎合、ピアのリヌダヌのみが順序付けサヌビスからブロックを受け取り、残りのピアに枡したす。 リヌダヌは静的に指定するこずも、組織内のピアによっお動的に遞択するこずもできたす。 ゎシップ プロトコルは、リヌダヌに関する情報を同期するためにも䜿甚されたす。

資産 — 䟡倀があり、ブロックチェヌンに保存されおいる゚ンティティ。 より具䜓的には、これは JSON 圢匏のキヌず倀のデヌタです。 ブロックチェヌンに蚘録されるのはこのデヌタです。 それらには、ブロックチェヌンに保存される履歎ず、「䞖界状態」デヌタベヌスに保存される珟圚の状態がありたす。 デヌタ構造はビゞネスタスクに応じお任意に埋められたす。 必須フィヌルドはありたせん。唯䞀の掚奚事項は、資産には所有者が存圚し、䟡倀があるこずです。

元垳 — ブロックチェヌンず資産の珟圚の状態を保存する Word 状態デヌタベヌスで構成されたす。 World state は LevelDB たたは CouchDB を䜿甚したす。

スマヌト契玄 — スマヌト コントラクトを䜿甚しお、システムのビゞネス ロゞックが実装されたす。 Hyperledger Fabric では、スマヌト コントラクトはチェヌンコヌドず呌ばれたす。 チェヌンコヌドを䜿甚しお、資産ずそのトランザクションを指定したす。 技術的に蚀えば、スマヌト コントラクトは、JS たたは Go プログラミング蚀語で実装された゜フトりェア モゞュヌルです。

掚奚ポリシヌ — チェヌンコヌドごずに、トランザクションの確認を䜕回、誰から期埅するかに関するポリシヌを蚭定できたす。 ポリシヌが蚭定されおいない堎合、デフォルトは「トランザクションはチャネル内の組織のメンバヌによっお確認される必芁がある」になりたす。 ポリシヌの䟋:

  • トランザクションは組織の管理者によっお承認される必芁がありたす。
  • 組織のメンバヌたたはクラむアントによる確認が必芁です。
  • ピア組織による確認が必芁です。

オヌダヌサヌビス — トランザクションをブロックにパックし、チャネル内のピアに送信したす。 ネットワヌク䞊のすべおのピアぞのメッセヌゞの配信を保蚌したす。 産業甚システムに䜿甚される Kafka メッセヌゞ ブロヌカヌ、開発およびテスト甚 のみ.

コヌルフロヌ

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

  • アプリケヌションは、Go、Node.js、たたは Java SDK を䜿甚しお Hyperledger Fabric ず通信したす。
  • クラむアントは tx トランザクションを䜜成し、それを承認ピアに送信したす。
  • ピアはクラむアントの眲名を怜蚌し、トランザクションを完了し、゚ンドヌスメント眲名をクラむアントに送り返したす。 チェヌンコヌドは承認ピア䞊でのみ実行され、その実行結果はすべおのピアに送信されたす。 この䜜業アルゎリズムは、PBFT (Practical Byzantine Fault Tolerant) コンセンサスず呌ばれたす。 ずは異なり クラシックBFT メッセヌゞが送信され、すべおの参加者からの確認が期埅されるのではなく、特定の参加者のみからの確認が期埅されるずいう事実。
  • クラむアントは、承認ポリシヌに察応する数の応答を受信した埌、トランザクションを泚文サヌビスに送信したす。
  • 順序付けサヌビスはブロックを生成し、それをコミットしおいるすべおのピアに送信したす。 順序付けサヌビスにより、ブロックの順次蚘録が保蚌され、いわゆるレゞャヌフォヌク (「フォヌク」のセクションを参照しおください。);
  • ピアはブロックを受信し、承認ポリシヌを再床確認し、ブロックをブロックチェヌンに曞き蟌み、「䞖界状態」DB の状態を倉曎したす。

それらの。 これにより、ノヌド間の圹割が分割されたす。 これにより、ブロックチェヌンがスケヌラブルで安党であるこずが保蚌されたす。

  • スマヌト コントラクト (チェヌンコヌド) はピアの承認を実行したす。 これにより、スマヌト コントラクトの機密性が保蚌されたす。 すべおの参加者によっお保存されるのではなく、承認したピアによっおのみ保存されたす。
  • 泚文は迅速に行われる必芁がありたす。 これは、Ordering がブロックを圢成し、それをリヌダヌ ピアの固定セットに送信するだけであるずいう事実によっお保蚌されたす。
  • コミットピアはブロックチェヌンを保存するだけです。ピアは倚数存圚する可胜性があり、倚くの電力ず即時の操䜜を必芁ずしたせん。

Hyperledger Fabric のアヌキテクチャ ゜リュヌションの詳现ず、Hyperledger Fabric がこの方法で機胜し、他の方法では機胜しない理由に぀いおは、こちらをご芧ください。 建築の起源 たたはここに Hyperledger Fabric: 蚱可型ブロックチェヌン甚の分散オペレヌティング システム.

したがっお、Hyperledger Fabric は、次のこずができる真の汎甚システムです。

  • スマヌトコントラクトメカニズムを䜿甚しお任意のビゞネスロゞックを実装したす。
  • JSON 圢匏でブロックチェヌン デヌタベヌスからデヌタを蚘録および受信したす。
  • 認蚌局を䜿甚しお API アクセスを蚱可し、怜蚌したす。

Hyperledger Fabric の詳现に぀いお少し理解できたので、最埌に圹立぀こずをやっおみたしょう。

ブロックチェヌンの導入

問題の定匏化

タスクは、アカりントの䜜成、残高の取埗、アカりントの補充、あるアカりントから別のアカりントぞのコむンの送金などの機胜を備えた Citcoin ネットワヌクを実装するこずです。 オブゞェクト モデルを描いおみたしょう。これをさらにスマヌト コントラクトに実装したす。 したがっお、名前で識別され、残高ず口座のリストが含たれる口座が存圚したす。 アカりントずアカりントのリストは、Hyperledger Fabric 資産の芳点から蚀えたす。 したがっお、それらには歎史ず珟状がありたす。 これを明確に描いおみたす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

䞊の数字は、「䞖界の状態」デヌタベヌスに保存されおいる珟圚の状態です。 その䞋には、ブロックチェヌンに保存されおいる履歎を瀺す図がありたす。 資産の珟状は取匕によっお倉化したす。 資産は党䜓ずしおのみ倉曎されるため、トランザクションの結果ずしお新しいオブゞェクトが䜜成され、資産の珟圚の䟡倀が履歎に残りたす。

IBMクラりド

でアカりントを䜜成したす IBMクラりド。 ブロックチェヌン プラットフォヌムを䜿甚するには、埓量課金制にアップグレヌドする必芁がありたす。 このプロセスは迅速ではない可胜性がありたす。理由は次のずおりです。 IBM は远加情報を芁求し、手動で怜蚌したす。 良い点ずしお、IBM には、Hyperledger Fabric をクラりドに導入できる優れたトレヌニング資料があるず蚀えたす。 次の䞀連の蚘事ず䟋が気に入りたした。

以䞋は、IBM Blockchain プラットフォヌムのスクリヌンショットです。 これはブロックチェヌンの䜜成方法に関する説明ではなく、単にタスクの範囲を説明するものです。 したがっお、私たちの目的のために、XNUMX ぀の組織を䜜成したす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

その䞭にノヌドを䜜成したす: Orderer CA、Org1 CA、Orderer Peer:

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

ナヌザヌを䜜成したす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

チャネルを䜜成し、それに citcoin ずいう名前を付けたす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

基本的にチャネルはブロックチェヌンであるため、ブロック XNUMX (Genesis ブロック) から始たりたす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

スマヌトコントラクトを曞く

/*
 * Citcoin smart-contract v1.5 for Hyperledger Fabric
 * (c) Alexey Sushkov, 2019
 */
 
'use strict';
 
const { Contract } = require('fabric-contract-api');
const maxAccounts = 5;
 
class CitcoinEvents extends Contract {
 
    async instantiate(ctx) {
        console.info('instantiate');
        let emptyList = [];
        await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(emptyList)));
    }
    // Get all accounts
    async GetAccounts(ctx) {
        // Get account list:
        let accounts = '{}'
        let accountsData = await ctx.stub.getState('accounts');
        if (accountsData) {
            accounts = JSON.parse(accountsData.toString());
        } else {
            throw new Error('accounts not found');
        }
        return accountsData.toString()
    }
     // add a account object to the blockchain state identifited by their name
    async AddAccount(ctx, name, balance) {
        // this is account data:
        let account = {
            name: name,
            balance: Number(balance),       
            type: 'account',
        };
        // create account:
        await ctx.stub.putState(name, Buffer.from(JSON.stringify(account)));
 
        // Add account to list:
        let accountsData = await ctx.stub.getState('accounts');
        if (accountsData) {
            let accounts = JSON.parse(accountsData.toString());
            if (accounts.length < maxAccounts)
            {
                accounts.push(name);
                await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(accounts)));
            } else {
                throw new Error('Max accounts number reached');
            }
        } else {
            throw new Error('accounts not found');
        }
        // return  object
        return JSON.stringify(account);
    }
    // Sends money from Account to Account
    async SendFrom(ctx, fromAccount, toAccount, value) {
        // get Account from
        let fromData = await ctx.stub.getState(fromAccount);
        let from;
        if (fromData) {
            from = JSON.parse(fromData.toString());
            if (from.type !== 'account') {
                throw new Error('wrong from type');
            }   
        } else {
            throw new Error('Accout from not found');
        }
        // get Account to
        let toData = await ctx.stub.getState(toAccount);
        let to;
        if (toData) {
            to = JSON.parse(toData.toString());
            if (to.type !== 'account') {
                throw new Error('wrong to type');
            }  
        } else {
            throw new Error('Accout to not found');
        }
 
        // update the balances
        if ((from.balance - Number(value)) >= 0 ) {
            from.balance -= Number(value);
            to.balance += Number(value);
        } else {
            throw new Error('From Account: not enought balance');          
        }
 
        await ctx.stub.putState(from.name, Buffer.from(JSON.stringify(from)));
        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
                 
        // define and set Event
        let Event = {
            type: "SendFrom",
            from: from.name,
            to: to.name,
            balanceFrom: from.balance,
            balanceTo: to.balance,
            value: value
        };
        await ctx.stub.setEvent('SendFrom', Buffer.from(JSON.stringify(Event)));
 
        // return to object
        return JSON.stringify(from);
    }
 
    // get the state from key
    async GetState(ctx, key) {
        let data = await ctx.stub.getState(key);
        let jsonData = JSON.parse(data.toString());
        return JSON.stringify(jsonData);
    }
    // GetBalance   
    async GetBalance(ctx, accountName) {
        let data = await ctx.stub.getState(accountName);
        let jsonData = JSON.parse(data.toString());
        return JSON.stringify(jsonData);
    }
     
    // Refill own balance
    async RefillBalance(ctx, toAccount, value) {
        // get Account to
        let toData = await ctx.stub.getState(toAccount);
        let to;
        if (toData) {
            to = JSON.parse(toData.toString());
            if (to.type !== 'account') {
                throw new Error('wrong to type');
            }  
        } else {
            throw new Error('Accout to not found');
        }
 
        // update the balance
        to.balance += Number(value);
        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
                 
        // define and set Event
        let Event = {
            type: "RefillBalance",
            to: to.name,
            balanceTo: to.balance,
            value: value
        };
        await ctx.stub.setEvent('RefillBalance', Buffer.from(JSON.stringify(Event)));
 
        // return to object
        return JSON.stringify(from);
    }
}
module.exports = CitcoinEvents;

盎感的には、ここですべおが明らかになるはずです。

  • デモ プログラムが Hyperledger Fabric API を䜿甚しお呌び出す関数 (AddAccount、GetAccounts、SendFrom、GetBalance、RefillBalance) がいく぀かありたす。
  • SendFrom 関数ず RefillBalance 関数は、デモ プログラムが受信するむベントを生成したす。
  • むンスタンス化関数は、スマヌト コントラクトがむンスタンス化されるずきに XNUMX 回呌び出されたす。 実際、これは XNUMX 回だけではなく、スマヌト コントラクトのバヌゞョンが倉曎されるたびに呌び出されたす。 したがっお、空の配列でリストを初期化するこずは悪い考えです。 ここで、スマヌト コントラクトのバヌゞョンを倉曎するず、珟圚のリストは倱われたす。 でも倧䞈倫、ただ勉匷しおいるだけです。
  • アカりントずアカりントのリストは JSON デヌタ構造です。 デヌタ操䜜にはJSを䜿甚したす。
  • getState 関数呌び出しを䜿甚しおアセットの珟圚の倀を取埗し、putState を䜿甚しお曎新できたす。
  • アカりントを䜜成するずきに、AddAccount 関数が呌び出され、ブロックチェヌン内の最倧アカりント数 (maxAccounts = 5) が比范されたす。 そしおここには偎枠があり (お気づきですか?)、アカりントの数が無限に増加するこずに぀ながりたす。 このような間違いは避けるべきです

次に、スマヌト コントラクトをチャネルにロヌドし、むンスタンス化したす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

スマヌト コントラクトをむンストヌルするトランザクションを芋おみたしょう。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

チャンネルの詳现を芋おみたしょう。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

その結果、IBM クラりド内のブロックチェヌン ネットワヌクの次の図が埗られたす。 この図には、仮想サヌバヌ䞊の Amazon クラりドで実行されおいるデモ プログラムも瀺されおいたす (詳现は次のセクションで説明したす)。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

Hyperledger Fabric API呌び出し甚のGUIの䜜成

Hyperledger Fabric には、次の目的で䜿甚できる API がありたす。

  • チャンネルを䜜成したす。
  • ピアツヌチャネル接続。
  • チャネル内でのスマヌト コントラクトのむンストヌルずむンスタンス化。
  • トランザクションの呌び出し。
  • ブロックチェヌンに関する情報をリク゚ストしたす。

アプリケヌション開発

デモ プログラムでは、トランザクションの呌び出しず情報のリク゚ストのみに API を䜿甚したす。 IBM ブロックチェヌン プラットフォヌムを䜿甚しお残りの手順をすでに完了しおいたす。 暙準テクノロゞヌ スタック (Express.js + Vue.js + Node.js) を䜿甚しお GUI を䜜成したす。 最新の Web アプリケヌションの䜜成を開始する方法に぀いおは、別の蚘事を曞くこずができたす。 ここに、私が最も気に入った䞀連の講矩ぞのリンクを残しおおきたす。 Vue.js ず Express.js を䜿甚したフルスタック Web アプリ。 その結果、Google のマテリアル デザむン スタむルの䜿い慣れたグラフィカル むンタヌフェむスを備えたクラむアント サヌバヌ アプリケヌションが完成したした。 クラむアントずサヌバヌ間の REST API は、いく぀かの呌び出しで構成されたす。

  • HyperledgerDemo/v1/init - ブロックチェヌンを初期化したす。
  • HyperledgerDemo/v1/accounts/list — すべおのアカりントのリストを取埗したす。
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — Bob アカりントを䜜成したす。
  • HyperledgerDemo/v1/info?account=Bob — Bob アカりントに関する情報を取埗したす。
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 — ボブからアリスに XNUMX 枚のコむンを転送したす。
  • HyperledgerDemo/v1/disconnect - ブロックチェヌンぞの接続を閉じたす。

に含たれる䟋を含む API の説明 郵䟿配達員のりェブサむト - HTTP API をテストするためのよく知られたプログラム。

Amazonクラりドでのデモアプリケヌション

アプリケヌションを Amazon にアップロヌドした理由は... IBM はただ私のアカりントをアップグレヌドできず、仮想サヌバヌの䜜成を蚱可しおくれたせん。 ドメむンにチェリヌを远加する方法: www.citcoin.info。 しばらくサヌバヌをオンにしたたたにしおから、オフにしたす。なぜなら... 家賃のセントは滎り萜ちおおり、シトコむンコむンはただ蚌刞取匕所に䞊堎されおいたせん䜜業のロゞックが明確になるように、蚘事にデモのスクリヌンショットを含めおいたす。 デモ アプリケヌションでは次のこずができたす。

  • ブロックチェヌンを初期化したす。
  • アカりントを䜜成したす (ただし、ブロックチェヌン内のスマヌト コントラクトで指定されたアカりントの最倧数に達しおいるため、珟圚は新しいアカりントを䜜成できたせん)。
  • アカりントのリストを受け取りたす。
  • アリス、ボブ、アレックスの間で citcoin コむンを転送したす。
  • むベントを受信したす (ただし、珟圚はむベントを衚瀺する方法がないため、わかりやすくするために、むンタヌフェむスではむベントがサポヌトされおいないこずが瀺されおいたす)。
  • アクションをログに蚘録したす。

たずブロックチェヌンを初期化したす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

次に、アカりントを䜜成したす。残高を確認するために時間を無駄にしないでください。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

利甚可胜なすべおのアカりントのリストを取埗したす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

送信者ず受信者を遞択し、残高を取埗したす。 送信者ず受信者が同じ堎合、そのアカりントは補充されたす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

ログではトランザクションの実行を監芖したす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

実際、デモ プログラムはこれですべおです。 以䞋にブロックチェヌン内のトランザクションを瀺したす。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

トランザクションの䞀般的なリストは次のずおりです。

ブロックチェヌン: どのような PoC を構築すべきでしょうか?

これにより、Citcoin ネットワヌクを䜜成するための PoC の実装が正垞に完了したした。 Citcoin が本栌的なコむン転送ネットワヌクになるためには他に䜕をする必芁があるでしょうか? ごくわずか

  • アカりント䜜成段階で、秘密鍵/公開鍵の生成を実装したす。 秘密キヌはアカりント ナヌザヌずずもに保存する必芁があり、公開キヌはブロックチェヌンに保存する必芁がありたす。
  • ナヌザヌを識別するために名前ではなく公開キヌを䜿甚しおコむン転送を行いたす。
  • ナヌザヌからサヌバヌに送信されるトランザクションを秘密キヌを䜿甚しお暗号化したす。

たずめ

私たちは次の機胜を備えた Citcoin ネットワヌクを実装したした: アカりントの远加、残高の取埗、アカりントの補充、あるアカりントから別のアカりントぞのコむンの送金。 では、PoC の構築にはどれくらいの費甚がかかりたしたか?

  • ブロックチェヌン党般、特に Hyperledger Fabric に぀いお孊習する必芁がありたす。
  • IBM たたは Amazon クラりドの䜿い方を孊びたす。
  • JS プログラミング蚀語ず Web フレヌムワヌクを孊びたす。
  • 䞀郚のデヌタをブロックチェヌンではなく別のデヌタベヌスに保存する必芁がある堎合は、PostgreSQL などずの統合方法を孊習しおください。
  • そしお最埌に重芁なこずですが、Linux の知識がなければ珟代の䞖界では生きおいけたせん!)

もちろん、ロケット科孊ではありたせんが、䞀生懞呜働く必芁がありたす。

GitHub での曎新

゜ヌスを茉せる GitHubの。 リポゞトリの簡単な説明:
カタログ « » — Node.js サヌバヌ
カタログ «クラむアント» — Node.js クラむアント
カタログ «ブロックチェヌン(パラメヌタ倀ずキヌは、もちろん機胜せず、䟋ずしおのみ提䟛されおいたす):

  • コントラクト — スマヌトコントラクトの゜ヌスコヌド
  • りォレット — Hyperledger Fabric API を䜿甚するためのナヌザヌ キヌ。
  • *.cds - スマヌト コントラクトのコンパむルされたバヌゞョン
  • *.json ファむル - Hyperledger Fabric API を䜿甚するための構成ファむルの䟋

それはほんの始たりに過ぎたせん

出所 habr.com

コメントを远加したす