トランザクションの作成、マイニング報酬、ミント、ガス料金


こんにちは、すべてで、私はどのようにコードのわずか60行で簡単なブロックを作成する方法をカバーしている.だから今日は、シリーズの第2部で取引を始めます.
あなたがまだBlockchainについて何も知らなかったならば、最初の記事を最初に読んでください.
また、これがすでにあなたのためにあまりに身近であるなら、P 2 Pネットワークを作成して、あなたの暗号通貨をリリースする方法についてのチェックアウトを考慮してください.
また、詳細については、YouTubeで私の新しい動画のこのチュートリアルを確実にチェックアウトする必要があります
  • 第1部Building a Blockchain (proof of work) in 60 lines of Javascript .
  • 第2部Creating Transaction, Mining reward, Mint and Gas fee on the Blockchain in Javascript .
  • Part 3 :Building P2P network and releasing your cryptocurrency on your blockchain .

  • 何を達成しようとしている
    基本的に、我々は送付者の財布アドレス、受信機の財布アドレスと我々が送っている量を含む取引の表現を持つ必要があります.トランザクションプールに追加し、新しいブロックを作成すると、保留中のトランザクションをそのブロックのデータに移動します.
    不正取引を防ぐために、キーペアと共に署名機構を使用します.そのキーペアには2つのキーが含まれます:秘密キー、および公開キー.公開鍵は財布のアドレスとして他に表示することができます、秘密キーは取引に署名するために使用されます.秘密鍵を握るだけで、アカウントの取引にサインできます.
    我々は、鋳造、初期のコインリリースとガス料金のようないくつかの他のものについて話します.
    これ以上言う、コーディングを開始しましょう!

    トランザクションクラス
    このように基本クラスがあります.
    class Transaction {
        constructor(from, to, amount) {
            this.from = from;
            this.to = to;
            this.amount = amount;
        }
    }
    

    鉱業取引
    に戻るBlockchain まず、すべての保留中のトランザクションを保持するトランザクションプールが必要です.
        this.transactions = [];
    
    さて、トランザクションを作成する方法があります.
        addTransaction(transaction) {
            this.transactions.push(transaction);
        }
    
    トランザクションのマイニング
        mineTransactions() {
            this.addBlock(new Block(Date.now().toString(), this.transactions));
    
            this.transactions = [];
        }
    
    我々は基本的に保留中のトランザクションを通過し、現在の保留中のトランザクションプールをクリアします.

    採鉱報酬
    誰も無料であなたのための私の取引を計算するための計算能力を失いたいので、鉱夫/バリデータのための報酬のいくつかのフォームを持っている必要があります.
    まず、我々はあなたが好きなものに設定することができますマイニング報酬プロパティを持っている、私は本当の理由で297に設定します.
        this.reward = 297;
    
    今、我々は鉱夫に報酬を転送するトランザクションを作成します.
        mineTransactions(rewardAddress) {
            this.addBlock(new Block(Date.now().toString(), [new Transaction(CREATE_REWARD_ADDRESS, rewardAddress, this.reward), ...this.transactions]));
    
            // Right now, we are just going assume the "from" address is something like this,
            // we will get back to this later in the next part of the article.
            this.transactions = [];
        }
    

    鋳造
    これはブロックチェーンの開発においてよく知られている用語ですが、それは単に、より多くのコインを追加する行為、または単純であるためにより多くのお金を印刷することを指します.チェーンが鉱夫報酬を与えるとき、それは実際には平均的な時間でコインを鋳造しています.

    署名
    我々は署名メカニズムを欠場することはできません、それが不可欠です!
    進む前に、いくつかの研究を行うことが重要ですsigning 第一に、それは暗号で人気のあるメカニズムです.
    私は、BitCointとEthereum - Secp 256 K 1で使用されるアルゴリズムを使用して、キーペアを生成します.
    我々はシンプルなままでいるので、それは非常に長いので、この記事よりも長くすることができますので、我々は自分でアルゴリズムを実装したくない.
    パッケージを使っているelliptic , 楕円もサポートしていることに注意してくださいCurve25519 その他のアルゴリズム
    NPMを通してインストールします.
    npm i elliptic
    

    キーペアを生成する
    これはキーペアを生成する例です.
    const EC = require("elliptic").ec, ec = new EC("secp256k1");
    
    const keyPair = ec.genKeyPair();
    // public key: keyPair.getPublic("hex")
    // private key: keyPair.getPrivate("hex")
    

    署名取引
    クリエイトアsign メソッドTransaction クラス
        sign(keyPair) {
            // Check if the public key matches the "from" address of the transaction
            if (keyPair.getPublic("hex") === this.from) {
                // Sign the transaction
                this.signature = keyPair.sign(SHA256(this.from + this.to + this.amount), "base64").toDER("hex");
            }
        }
    

    検証
    すべてのブロックが有効なトランザクションを持つ場合、チェインは有効です.
  • から、量は空ではありません.
  • 送付者のアドレスは、送られる量より多くのお金を持っています.
  • 署名はトランザクションのデータと一致します.
  • 第一に、私たちはBlockchain 利便性のためのアドレスのバランスを得るためのクラス.
    チェーンのトランザクション履歴に基づいてアドレスのバランスをとる方法を実装できます.
        getBalance(address) {
            let balance = 0;
    
            this.chain.forEach(block => {
                block.data.forEach(transaction => {
                    // Because if you are the sender, you are sending money away, so your balance will be decremented.
                    if (transaction.from === address) {
                        balance -= transaction.amount;
                    }
    
                    // But if you are the receiver, you are receiving money, so your balance will be incremented.
                    if (transaction.to === address) {
                        balance += transaction.amount;
                    }
                })
            });
    
            return balance;
        }
    
    だから我々はこのような方法を我々のTransaction クラス
        isValid(tx, chain) {
            return (
                tx.from &&
                tx.to &&
                tx.amount &&
                chain.getBalance(tx.from) >= tx.amount &&
                ec.keyFromPublic(tx.from, "hex").verify(SHA256(tx.from + tx.to + tx.amount + tx.gas), tx.signature)
            );
        }
    
    インサイドBlock Class、有効なトランザクションがあるかどうかをチェックするメソッドを作成します.
        hasValidTransactions(chain) {
            return this.data.every(transaction => transaction.isValid(transaction, chain));
        }
    
    更新isValid メソッドBlockchain クラス
        if (
            currentBlock.hash !== currentBlock.getHash() || 
            prevBlock.hash !== currentBlock.prevHash || 
            !currentBlock.hasValidTransactions(blockchain)
        ) {
            return false;
        }
    
    さて、トランザクションをプールにプッシュする前に有効かどうかをチェックする必要があります.
        addTransaction(transaction) {
            if (transaction.isValid(transaction, this)) {
                this.transactions.push(transaction);
            }
        }
    
    さあ、戻ってみましょうminting 約束通り.第一に、私はちょうど鋳造のためのアドレスを作成します.
    const MINT_KEY_PAIR = ec.genKeyPair();
    const MINT_PUBLIC_ADDRESS = MINT_KEY_PAIR.getPublic("hex");
    
    新しいメソッド:
        mineTransactions(rewardAddress) {
            // Create a mint transaction for reward.
            const rewardTransaction = new Transaction(MINT_PUBLIC_ADDRESS, rewardAddress, this.reward);
            rewardTransaction.sign(MINT_KEY_PAIR);
    
            // We will add the reward transaction into the pool.
            this.addBlock(new Block(Date.now().toString(), [rewardTransaction, ...this.transactions]));
    
            this.transactions = [];
        }
    
    チェーンのアドレスには例外があります:我々がお金を印刷しているので、そのバランスはチェックされませんTransaction.isValid 同様に.また、その金額は、定義された報酬と全く同じでなければなりません.
        isValid(tx, chain) {
            return (
                tx.from &&
                tx.to &&
                tx.amount &&
                (chain.getBalance(tx.from) >= tx.amount || tx.from === MINT_PUBLIC_ADDRESS) &&
                ec.keyFromPublic(tx.from, "hex").verify(SHA256(tx.from + tx.to + tx.amount), tx.signature)
            );
        }
    

    最初の数枚のコインをリリース
    に戻るBlockchain クラスは、我々のジェネシスブロックにいくつかの変更を行います.我々は、1つのアドレス(最大希釈された市場キャップを作成する)のいくつかのコインを鋳造します.もし誰か私たちの通貨を買いたいなら、彼らは私たちにお金を貸してくれます.これも契約という.
    キーペアを最初に作成する
    const holderKeyPair = ec.genKeyPair();
    
    Genesisブロックでは、単にインクリメンタルコインリリースのトランザクションを作成します.
        // We will release 100000 coin
        const initalCoinRelease = new Transaction(MINT_PUBLIC_ADDRESS, holderKeyPair.getPublic("hex"), 100000);
        this.chain = [new Block(Date.now().toString(), [initalCoinRelease])];
    

    鋳造の問題
    場合は、誰かがmintingアドレスにアクセスできるかどうか疑問に思っている、我々は多くの不良金をプリントアウトできませんか?あなたは正しいでしょう、しかし、我々はピアツーピアネットワークで我々の問題の全てを取り扱うつもりです.
    Peer - to - Peerネットワークは、この問題を処理します.
  • は1以上のトランザクションを鋳造している.
  • ミント取引以外の1トランザクションより低いです、それは基本的に、彼が実際にいくつかの本当の取引を生じることなくブロックを追っていることを意味します.

  • ガス料金
    鉱夫の報酬もあるgas fee , しかし、それは少し異なります.それは鉱山労働者のための基本的なユーザーの報酬です.これは鉱業を鉱夫により魅力的にし、鉱業に使用されるエネルギーにも支払いを行い、人々はより鉱夫によってより迅速に選べられる高いガス料金を支払わなければならないだろう.
    私たちはgas 我々の財産Transaction クラス.
        class Transaction {
            // Gas will be set to 0 because we are making it optional
            constructor(from, to, amount, gas = 0) {
                this.from = from;
                this.to = to;
                this.amount = amount;
                this.gas = gas;
            }
    
            sign(keyPair) {
                if (keyPair.getPublic("hex") === this.from) {
                    // Add gas
                    this.signature = keyPair.sign(SHA256(this.from + this.to + this.amount + this.gas), "base64").toDER("hex");
                }
            }
    
            isValid(tx, chain) {
                return (
                    tx.from &&
                    tx.to &&
                    tx.amount &&
                    // Add gas
                    (chain.getBalance(tx.from) >= tx.amount + tx.gas || tx.from === MINT_PUBLIC_ADDRESS) &&
                    ec.keyFromPublic(tx.from, "hex").verify(SHA256(tx.from + tx.to + tx.amount + tx.gas), tx.signature)
                );
            }
        }
    
    我々は更新されますgetBalance 方法:
        getBalance(address) {
            let balance = 0;
    
            this.chain.forEach(block => {
                block.data.forEach(transaction => {
                    if (transaction.from === address) {
                        balance -= transaction.amount;
                        balance -= transaction.gas
                    }
    
                    if (transaction.to === address) {
                        balance += transaction.amount;
                    }
                })
            });
    
            return balance;
        }
    
    今、私たちは鉱夫にガス料金をあげるべきです.
        mineTransactions(rewardAddress) {
            let gas = 0;
    
            this.transactions.forEach(transaction => {
                gas += transaction.gas;
            });
    
            const rewardTransaction = new Transaction(MINT_PUBLIC_ADDRESS, rewardAddress, this.reward + gas);
            rewardTransaction.sign(MINT_KEY_PAIR);
    
            // Prevent people from minting coins and mine the minting transaction.
            if (this.transactions.length !== 0) this.addBlock(new Block(Date.now().toString(), [rewardTransaction, ...this.transactions]));
    
            this.transactions = [];
        }
    
    ブロックの検証方法も変更する必要があります.
        hasValidTransactions(chain) {
            let gas = 0, reward = 0;
    
            this.data.forEach(transaction => {
                if (transaction.from !== MINT_PUBLIC_ADDRESS) {
                    gas += transaction.gas;
                } else {
                    reward = transaction.amount;
                }
            });
    
            return (
                reward - gas === chain.reward &&
                this.data.every(transaction => transaction.isValid(transaction, chain)) && 
                this.data.filter(transaction => transaction.from === MINT_PUBLIC_ADDRESS).length === 1
            );
        }
    

    テスト
    // Your original balance is 100000
    
    const girlfriendWallet = ec.genKeyPair();
    
    // Create a transaction
    const transaction = new Transaction(holderKeyPair.getPublic("hex"), girlfriendWallet.getPublic("hex"), 100, 10);
    // Sign the transaction
    transaction.sign(holderKeyPair);
    // Add transaction to pool
    JeChain.addTransaction(transaction);
    // Mine transaction
    JeChain.mineTransactions(holderKeyPair.getPublic("hex"));
    
    // Prints out balance of both address
    console.log("Your balance:", JeChain.getBalance(holderKeyPair.getPublic("hex")));
    console.log("Your girlfriend's balance:", JeChain.getBalance(girlfriendWallet.getPublic("hex")));
    
    次のようになります.

    だから、それだ!必要に応じて完全なソースコードを示します.

    名誉ある言及
    閉じるこの動画はお気に入りから削除されています.
    ここで彼のgithubアカウントを確認できます.https://github.com/apple096/

    資源
    見つける:
  • Github


  • Viblo
  • この記事のYouTube版をチェックしてください.

  • Creating Transaction, Mining reward, Mint and Gas fee on the Blockchain in Javascript .