第四章財布

概要

目的は、トランザクションを管理するために、ユーザーに財布より高いレベルの抽象インタフェースを作成することです。

私たちの究極の目標は、ユーザーが簡単にできるようにすることです:

  • 新しいウォレットを作成します。
  • ビューウォレットの残高
  • 財布間の取引

これらのユーザーの発効は、これらの取引の前のセクションで説明した入力とoutpusの詳細を知る必要はありません後、我々は、トランザクションを管理できるようになります。ビットコインのネットワークと同様に、あなただけのあなただけの独自のアドレスを公開する必要がある一方で、他の人がお金のビットを与えることができるようになります、ビットコインは他の誰かに侵入することができるようになります対応するビットコインアドレスを入力する必要があります。

このセクションの完全なコードを参照してくださいここに

財布を生成します

このチュートリアルでは、初期化され、最も簡単な方法と財布のストレージ:ノード/財布/ PRIVATE_KEYこのファイルに格納されている暗号化されていない秘密鍵を。

const privateKeyLocation = 'node/wallet/private_key';

const generatePrivatekey = (): string => {
    const keyPair = EC.genKeyPair();
    const privateKey = keyPair.getPrivate();
    return privateKey.toString(16);
};

const initWallet = () => {
    //let's not override existing private keys
    if (existsSync(privateKeyLocation)) {
        return;
    }
    const newPrivateKey = generatePrivatekey();

    writeFileSync(privateKeyLocation, newPrivateKey);
    console.log('new wallet with private key created');
};

以前に述べたように、私たちの公開鍵(財布アドレス)は、秘密鍵によって推定されます。

const getPublicFromWallet = (): string => {
    const privateKey = getPrivateFromWallet();
    const key = EC.keyFromPrivate(privateKey, 'hex');
    return key.getPublic().encode('hex');
};

プライベートキーがファイルにプレーンテキストで保存されていることを言及する必要があることは非常に危険な習慣です。私達はちょうどのみプレゼンテーションを簡単にするために、次のように行います。同時に、財布は現在、唯一の秘密鍵をサポートしていますので、あなたは、公開鍵として新しいアドレスが必要な場合は、その後、私たちは、新しいウォレットを作成する必要があります。

ウォレットの残高が

前節で述べた検討中の文:あなたはチェーンブロック暗号の通貨を持っているが、実際には、「非消費者取引の出力」を参照して、受信者のアドレスが出力彼らの公開鍵のシリーズです。

これは、私たちが財布の残高は、その後、物事は非常にシンプルになるかどうかを確認することを意味します。あなただけの終了されるだろう一緒にお金の「非消費者取引の出力」レコード番号の下にあるすべてのアドレスが必要です。

const getBalance = (address: string, unspentTxOuts: UnspentTxOut[]): number => {
    return _(unspentTxOuts)
        .filter((uTxO: UnspentTxOut) => uTxO.address === address)
        .map((uTxO: UnspentTxOut) => uTxO.amount)
        .sum();
};

簡単にプレゼンテーションを行うために、我々はすべての個人情報のクエリアドレス財布のバランスを提供する必要はありません。言い換えれば、誰もが他人の口座残高を表示することができます。

トランザクションを生成します

金融取引を暗号化するには、これらの特徴点の入力と出力で取引を心配する必要はありません。しかし、彼は、ユーザBを与える場合は、ユーザーAのアカウントは、50枚のコインを持っているときに何が起こったのかバック取引、10枚のコインを送りますか?

この場合、システム10は、残りの40は、ユーザAのクレジットに返送される一方、Bに対応する公開鍵クレジットに送信します 換言すれば、消費の50のコイン源が完了しなければならないソースは通貨取引を出力するように割り当てられている場合、それは分割されなければなりません。トランザクションが単語を削除して出力の50枚のコインのソースである必要があります後、「消費者取引を出力しない」、2つの出力は、新たに生成された追加します。それが金融集計上の「消費者取引の出力がありません」変更されませんが、いくつかの通貨が取引され、アドレスが別のユーザーに属しています。

次の図は、上述したトランザクションを示しています。

シーンのより洗練されたポイントを見てみましょう:

  • ユーザーは、ほとんどのC 0コインを持ち始めています
  • 3つの取引レッツCが10、20を与えられた後、コイン
  • C Dは55枚のコインを転送したいです。

この場合、すべての3つの出力のユーザーC(それらの出力Cの公開鍵のためのアドレスで「非消費者トランザクション出力」)はD 55枚のコイン、残りの5枚のコインを過ごすために働きかけていますこれは、Cに返されます

それでは、どのコードのロジックとの上記の説明は、それを表現するのだろうか?まず、我々は、トランザクションに対応する入力を作成します。どのようにそれを作成するには?あなたがコインの十分な数を働きかけたことができます出力の(コイン枚数の硬貨の目標数に等しいより大きな出力を加算)まで、私たちは、送信者の公開鍵のエントリアドレスを横断する「トランザクションは、消費しませ出力します」。

const findTxOutsForAmount = (amount: number, myUnspentTxOuts: UnspentTxOut[]) => {
    let currentAmount = 0;
    const includedUnspentTxOuts = [];
    for (const myUnspentTxOut of myUnspentTxOuts) {
        includedUnspentTxOuts.push(myUnspentTxOut);
        currentAmount = currentAmount + myUnspentTxOut.amount;
        if (currentAmount >= amount) {
            const leftOverAmount = currentAmount - amount;
            return {includedUnspentTxOuts, leftOverAmount}
        }
    }
    throw Error('not enough coins to send transaction');
};

コードに示すように、我々は戻って送信者にleftOverAmount非消費の条件を満たしている、だけでなく、コインの必要な数の残りの部分の下にトランザクションを記録するために、これらのトランザクションの出力に加えて、見つけます。

これらの非消費者取引の出力を見つけた後、私たちは現在のトランザクションが対応する入力を作成することを考えることができます。

const toUnsignedTxIn = (unspentTxOut: UnspentTxOut) => {
    const txIn: TxIn = new TxIn();
    txIn.txOutId = unspentTxOut.txOutId;
    txIn.txOutIndex = unspentTxOut.txOutIndex;
    return txIn;
};
const {includedUnspentTxOuts, leftOverAmount} = findTxOutsForAmount(amount, myUnspentTxouts);
const unsignedTxIns: TxIn[] = includedUnspentTxOuts.map(toUnsignedTxIn);

アプローチは、主に、非消費者取引の出力に対応するtxOutId点の各入力は、上記の項目を見つけ、非常に簡単です。

2つの出力の例を作成する必要が続い:コインの残数が戻ってくるために必要なので、出力は受信者にあり、他の出力は、自分自身の送信元です。もちろん、入力は、取引の量と正確に一致指している場合はコインの総数はleftOverAmount 0という、我々は、ターゲットユーザーの十分に送信出力を作成する必要があります。

const createTxOuts = (receiverAddress:string, myAddress:string, amount, leftOverAmount: number) => {
    const txOut1: TxOut = new TxOut(receiverAddress, amount);
    if (leftOverAmount === 0) {
        return [txOut1]
    } else {
        const leftOverTx = new TxOut(myAddress, leftOverAmount);
        return [txOut1, leftOverTx];
    }
};

最後に、我々は、(トランザクションコンテンツのハッシュを行う)トランザクションIDを計算し、トランザクションが署名され、トランザクションは、各入力に最終的な署名を与えます。

const tx: Transaction = new Transaction();
    tx.txIns = unsignedTxIns;
    tx.txOuts = createTxOuts(receiverAddress, myAddress, amount, leftOverAmount);
    tx.id = getTransactionId(tx);

    tx.txIns = tx.txIns.map((txIn: TxIn, index: number) => {
        txIn.signature = signTxIn(tx, index, privateKey, unspentTxOuts);
        return txIn;
    });

財布を使用してください

私たちは、ユーザーが簡単に財布の機能を使用できるようにするために「/ mineTransaction」は、このAPIを提供します:

app.post('/mineTransaction', (req, res) => {
        const address = req.body.address;
        const amount = req.body.amount;
        const resp = generatenextBlockWithTransaction(address, amount);
        res.send(resp);
    });

コードに示されているように、ユーザは、トランザクションのアドレス番号を提供する必要は受信者がこのトランザクションAPIによって達成することができます。API私たちを更新しつつ、マイニングを行うために50元の取引通貨の合計を取得するために、その後のトランザクションの指定した受信者のアドレスと数に応じてトランザクションを完了し、最初の呼び出しの後に、これらの取引は、最終的に、ブロック内の新しい増加に記録されます「トランザクションは消費しませ出力します。」

テスト経験

  • スタート

私たちはすぐにテストのための2つのノードを開始できるように、テスト目的のために、あなたはパラメータの束を起動するたびに入力する必要がなく、package.jsonのためにいくつかの変更をスタートアップスクリプトを実行します。

npm run node1
npm run node 2

同時に、あなたは2番目のノードとノード1が自動的にP2P接続を確立されるように、PEERパラメータを追加して、2番目のノードを起動したとき。

"scripts": {
    "prestart": "npm run compile",
    "node1": "HTTP_PORT=3001 P2P_PORT=6001 WALLET=1 npm start ",
    "node2": "HTTP_PORT=3002 P2P_PORT=6002 WALLET=2 PEER=ws://localhost:6001 npm start ",
    "start": "node src/main.js",
    "compile": "tsc"
  },

最後に、新しく追加されたWALLETパラメータをサポートすることにより、我々は自動的に各ノードの財布を開始します、我々は財布やトランザクションの振る舞いを観察することがはるかに容易になります。

  • 追加のインターフェイス見る「untraded出力コンシューマを。」

「消費者untraded出力」ので、私たちは、基礎となる取引を行う際に、このリストは、非常に重要です。したがって、内部のデータ変更を表示するための追加のインタフェースを提供することが必要です。あなたは「するには、GETによって要求を送信することができます:// localhostの3001 / unspentTransactionOutputs HTTPインターフェースは、リストを取得するために」。

あなたは二つのノードを果たした場合、使用ポート3001と3002が可能であることに注意してください。リストはリストとして配布され、私たちのブロック鎖れ、同期ネットワーク全体です。

あなたはこれらを持っていたら、あなたは簡単に財布や取引機能は郵便配達を通じて体験するために、適切なインターフェースを呼び出すことができます。

概要

私たちは、単純な取引のために暗号化されていない財布機能を実装しました。トレーディングアルゴリズム(インターフェース・ロジックに関連付けられmineTransaction)が2つだけの受信機出力の最大有することができるが(一つの受信機を、一つは自分のある)、私たちのボトムブロック鎖インタフェースは、任意の数の出力をサポートすることができます。たとえば、入力を作成することができます50枚のコインで、出力は5、15、30通貨の取引ですが、手動でデータを記入し、達成するために/ mineRawBlockにこのインタフェースを呼び出す必要があります。

これまでのところ、我々はトランザクション、またはマイニングを実施する必要性を行い、トランザクション情報は、内部の新しいブロックに追加することができます。トランザクションをブロックしません私たちの現在の各ノードは、情報の任意の交換を行う際に記録されていません。これらの問題は、次の章で解決されます。

このセクションの完全なコードを参照してくださいここに

章V

承認を得て転載珠海書き込みの世界評議会によるこの記事Fenduo、このようなポイントのように、星に与えるGithubの上、このようなプロジェクトとして、Tucaoをコメントしてくださいは、非常に高く評価されます。

おすすめ

転載: blog.csdn.net/zhubaitian/article/details/93346504