通貨取引の暗号化


crypto-transactions


領地式証明


暗号学では、ある事項が本当であることを相手に証明する人がいる場合、その文章が本当に偽物であるかどうかを除いて、何も露出しないインタラクティブなプログラムです.
情報を漏らさずに知っていることを証明する
硬貨については、硬貨の固有情報や取引漏れがない場合に硬貨を保有し取引することを意味する.

1.整合性


ある文章が本当なら、正直な証明者は検証者に事実を受け入れることができるはずだ.

2.頑丈性


いかなる文章も虚偽であり、いかなる不誠実な証明者も正直な検証者にこの文章が本当だと信じさせてはいけない.

3.領地知識性


もしある文が本当なら、検証者は文の真偽以外に何も知らない.

例(比喩)



証明者と検証者がいる場合、証明者は洞窟内の秘密ドアの鍵を持っている.
洞窟はAとB通路で、入り口の向こうに秘密のドアがあります.
証明人は検証者に鍵を持っていることを伝えるべきだが、彼は自分の秘密を他の人に知られたくない.
このとき,検証者は洞窟の外で待機し,証明者はAとBのどこにでも入る.検証者は証明者がどこに入ったか分からない.
検証者が任意にAまたはBを選択して証明者を出させると、証明者は検証者が呼ぶ通路を通って出る.
鍵があれば、証明者は任意の通路を選択することができ、鍵がなければ50%の確率で出てくる.
鍵がなければ、この実験を20回繰り返すだけで100万分の1の確率がある.
この実験は,検証者以外に何の情報も提供せず,カメラで録画しても他の人に証明できないが,検証者にのみ有効である.
現在領地式証明を用いている硬貨はZcash,Z硬貨,Pvix,Kcurrent,Spectreなどである.

公開鍵の暗号化と署名


公開鍵暗号化は、秘密鍵と一対の鍵と呼ばれる一対の鍵を含む.

公開鍵は秘密鍵から派生することができ、秘密鍵は公開鍵から派生することができない.
公開鍵(名前のように)は、誰にでも安全に共有できます.

秘密鍵と公開鍵


有効な秘密鍵は任意の32バイト文字列です
有効な公開鍵は64バイト文字列です

トランザクション構造


トランザクションの理由入力と出力の2つの部分から構成されています
出力はコインを送る位置を指定します.
入力は、実際に伝送された硬貨がスパイラルに存在し、送信者が所有する証拠を提供する.

トランザクション出力


class TxOut {
    constructor (address, amount){
        this.address = address;///주소 : ECDSA 공개키
        this.amount = amount;// 코인수량
    }
}

トランザクション入力

class TxIn {
    constructor(txOutId, yxOutIndex, signature){
        this.txOutId = txOutId;
        this.TxOutIndex = TxOutIndex;
        this.signature = signature;
    }
}

トランザクション構造

class Transaction {
    constructor (id, txIns, txOuts){
        this.id = id;
        this.txIns = txIns;
        txIns.txOuts = txOuts;
    }
}

取引口座


トランザクションIDは、トランザクションコンテンツからハッシュ値を取得することによって計算される.ただし、txIdsの署名は後でトランザクションに追加されるため、トランザクションハッシュテーブルには含まれません.
const getTranxaction = (transaction) => {
    const txInContent = transaction.txIns
    .map((txIn) => txIn.txOutId + txIn.TxOutIndex )
    .reduce((a,b) => a + b, '')

    const txOutContent = transaction.txOuts
    .map((txOut) =>  txOut.address + txOut.amount)
    .reduce((a,b) => a + b, '')

    return CryptoJS.SHA256(txInContent + txOutContent).toString();

}

取引署名

const signTxIn = (transaction, txInIndex, privateKey, aUnspentTxOuts) => {
    const txIn = transaction.txIns[txInIndex];
    const dataToSign = transaction.id;
    const referencedUnspentTxOut = findUnspentTxOut(txIn.txOutId, txIn.txOutIndex, aUnspentTxOuts);
    const referencedAddress = referencedUnspentTxOut.address;
    const key = ec.keyFromPrivate(privateKey, 'hex');
    const signature = toHexString(key.sign(dataTosing).toDER());
    return signature;

}
重要なのは、取引に署名した後、取引を変更することはできません.取引は公開されているので、誰もが取引がブロックチェーンに入る前に取引にアクセスすることができます.
トランザクション入力に署名する場合は、txIdのみ署名します.トランザクションの内容を変更すると、txIdはトランザクションと署名を無効にするように変更されます.

未使用のトランザクション出力


トランザクション出力を使用しないデータ構造
class UnspentTxOut {
   txOutId;;
   txOutIndex ;
   address;
   amount;

   constructor(txOutId, txOutIndex, address, amount) {
       this.txOutId = txOutId;
       this.txOutIndex = txOutIndex;
       this.address = address;
       this.amount = amount;
   }
}

未使用のトランザクション出力の更新


未使用のトランザクション出力を最初にスキャン
 const newUnspentTxOuts = aTransactions
       .map(t => {
           return t.txOuts.map((txOut, index) => (
               new UnspentTxOut(t.id, index, txOut.address, txOut.amount)
           ))
       })
       .reduce((a, b) => a.concat(b), []);
新しいトランザクションの検索
 const consumedTxOuts = aTransactions
       .map((t) => t.txIns)
       .reduce((a, b) => a.concat(b), [])
       .map((txIn) => new UnspentTxOut(txIn.txOutId, txIn.txOutIndex, '', 0));
既存のトランザクション出力の削除と追加
  const resultingUnspentTxOuts = aUnspentTxOuts
       .filter(((uTxO) => !findUnspentTxOut(uTxO.txOutId, uTxO.txOutIndex, consumedTxOuts)))
       .concat(newUnspentTxOuts);

トランザクション検証


正しいトランザクション構造
const validateTransaction = (transaction, aUnspentTxOuts) => {
   if (!isValidTransactionStructure(transaction)) {
       return false;
   }
トランザクションIDの検証
 if (getTransactionId(transaction) !== transaction.id) {
        console.log('invalid tx id: ' + transaction.id);
        return false;
    }
取引の検証txIns
 const hasValidTxIns = transaction.txIns
        .map((txIn) => validateTxIn(txIn, transaction, aUnspentTxOuts))
        .reduce((a, b) => a && b, true);
    if (!hasValidTxIns) {
        console.log('referenced txOut not found: ' + transaction.id);
        return false;
    }
トランザクションtxOutsの検証-txInsの合意値はtxOutsの和と同じですか?
  const totalTxInValues = transaction.txIns
       .map((txIn) => getTxInAmount(txIn, aUnspentTxOuts))
       .reduce((a, b) => (a + b), 0);
   const totalTxOutValues = transaction.txOuts
       .map((txOut) => txOut.amount)
       .reduce((a, b) => (a + b), 0);
   if (totalTxOutValues !== totalTxInValues) {
       console.log('totalTxOutValues !== totalTxInValues in tx: ' + transaction.id);
       return false;
   }

貨幣取引

const COINBASE_AMOUNT = 50; // 입력은 없고 출력만..블럭을 찾으면 50개동전을 보상
Coinbaseの検証
const validateCoinbaseTx = (transaction, blockIndex) => {
   console.log("transaction============ \n", transaction)
   console.log("transaction.txouts============ \n", transaction.txOuts)
   if (transaction == null) {
       console.log('the first transaction in the block must be coinbase transaction');//첫 transaction이 코인베이스 거래인지
       return false;
   }
   if (getTransactionId(transaction) !== transaction.id) {
       console.log('invalid coinbase tx id: ' + transaction.id); // 유효한 transaction id 인지
       return false;
   }
   if (transaction.txIns.length !== 1) {
       console.log('one txIn must be specified in the coinbase transaction'); //txIn 하나는 거래하나씩 지정
       return;
   }
   if (transaction.txIns[0].txOutIndex !== blockIndex) {
       console.log('the txIn index in coinbase tx must be the block height'); //처음 txIn인덱스는 블록높이와 같아야 함
       return false;
   }
   if (transaction.txOuts.length !== 1) {
       console.log('invalid number of txOuts in coinbase transaction'); // txOuts 하나는 거래하나씩 지정
       return false;
   }
   if (transaction.txOuts[0].amount !== COINBASE_AMOUNT) {
       console.log('invalid coinbase amount in coinbase transaction'); // txOuts양이 코인 전체의 값과 같은지
       return false;
   }
   return true;
};