成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

node.js與比特幣

2json / 991人閱讀

摘要:交易我們都知道得到比特幣需要挖礦,其實(shí)挖礦也屬于一種交易,不過(guò)是一種沒(méi)有確定交易輸入的一種交易,它也被稱作交易。這筆交易由轉(zhuǎn)賬發(fā)發(fā)起,因此需要提供轉(zhuǎn)賬方的私鑰進(jìn)行解鎖腳本。驗(yàn)證通過(guò)則證明這是屬于轉(zhuǎn)賬方的,可以用于交易。

BTC中的utxo模型

BTC中引入了許多創(chuàng)新的概念與技術(shù),區(qū)塊鏈、PoW共識(shí)、RSA加密、萌芽階段的智能合約等名詞是經(jīng)常被圈內(nèi)人所提及,誠(chéng)然這些創(chuàng)新的實(shí)現(xiàn)使得BTC變成了一種有可靠性和安全性保證的封閉生態(tài)系統(tǒng),但是在這個(gè)BTC生態(tài)中如果沒(méi)有搭配區(qū)塊鏈模式的轉(zhuǎn)賬模塊,那么貨幣的流通屬性也就無(wú)從談起了。若要實(shí)現(xiàn)轉(zhuǎn)賬交易模塊, “是否采用傳統(tǒng)的賬戶模型實(shí)現(xiàn)交易;如何在區(qū)塊鏈上存儲(chǔ)交易信息,如何實(shí)現(xiàn)信息壓縮;如何驗(yàn)證交易信息;系統(tǒng)的最大交易并發(fā)量”等問(wèn)題確實(shí)值得思考。

BTC一一解決了這些,它放棄了傳統(tǒng)的基于賬戶的交易模型,而是采用基于區(qū)塊鏈存儲(chǔ)的utxo(unspent transaction output)模型。筆者嘗試分析了為什么不使用傳統(tǒng)的賬戶模型:

BTC的存儲(chǔ)單元為區(qū)塊鏈,區(qū)塊鏈的數(shù)據(jù)結(jié)構(gòu)本質(zhì)上是單向鏈表,它并不是傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù),無(wú)法新建賬戶表

存儲(chǔ)壓力。如果采用傳統(tǒng)的方式,則賬戶表會(huì)隨著時(shí)間的推移不停地增大,為后續(xù)的表的分片與備份造成很大困難

易造成隱私泄露。賬戶表的信息會(huì)直觀的暴露余額等敏感信息

utxo模型則很有技巧的避免了這些,在utxo模型下實(shí)現(xiàn)的每一筆交易,都不需要顯式的提供轉(zhuǎn)賬地址和接收地址(utxo中沒(méi)有賬戶,也不需要提供地址),只需提供這比交易的 交易輸入交易輸出 即可,而交易輸入與交易輸出又是什么?

交易輸入指向一筆交易輸出,而且 “這筆交易輸出是可以供轉(zhuǎn)賬者消費(fèi)的,因此這筆交易輸出也被稱作utxo(未花費(fèi)交易輸出)”,它包括“某一筆交易、指向這筆交易的某個(gè)可用交易輸出的索引值和一個(gè)解鎖腳本”。這個(gè)解鎖腳本用來(lái)驗(yàn)證某筆可用的消費(fèi)輸出是否可以被提供解鎖腳本的人所使用。

交易輸出則是存儲(chǔ)BTC“余額”的一個(gè)數(shù)據(jù)結(jié)構(gòu),它廣義上包括兩部分:BTC的數(shù)量和一個(gè)鎖定腳本。 BTC的數(shù)量可以理解為余額,表示這筆交易產(chǎn)生的結(jié)果;而鎖定腳本則是用某種算法鎖定這個(gè)BTC余額,直到某人可以提供解鎖該腳本的數(shù)據(jù)鑰匙,這比數(shù)額BTC才會(huì)被這個(gè)人所消費(fèi)。

從這個(gè)角度看,一筆交易會(huì)包含若干個(gè)交易輸入,同時(shí)產(chǎn)生若干個(gè)交易輸出。這些交易輸入都會(huì)指向之前某筆交易的未被消費(fèi)輸出(utxo),并提供各自的解鎖腳本以證明這些utxo里的BTC是屬于轉(zhuǎn)賬方;同時(shí)將轉(zhuǎn)賬產(chǎn)生的所有交易輸出用對(duì)應(yīng)方的公鑰進(jìn)行加密(此處是為了更好的理解才解釋為公鑰加密,實(shí)質(zhì)上是公鑰哈希,即btc地址進(jìn)行逆向base58編碼的一段字符串),鎖定這幾筆交易輸出,等待交易輸入中的解鎖腳本解鎖。

所以,BTC沒(méi)有賬戶的概念,所有的“余額”都在區(qū)塊鏈上,不過(guò)這些余額都已經(jīng)被加密了,只有提供私鑰和簽名的人才可以使用對(duì)應(yīng)的utxo的余額,因此這就是為什么BTC持有者必須保存好自己的私鑰的原因。

UTXO的node.js實(shí)現(xiàn) 交易輸入
export class Input {
    private txId: string;
    private outputIndex: number;
    private unlockScript: string;

    public get $txId(): string {
        return this.txId;
    }

    public set $txId(value: string) {
        this.txId = value;
    }
    
    public get $outputIndex(): number {
        return this.outputIndex;
    }

    public set $outputIndex(value: number) {
        this.outputIndex = value;
    }

    public get $unlockScript(): string {
        return this.unlockScript;
    }

    public set $unlockScript(value: string) {
        this.unlockScript = value;
    }
    
    constructor(txId: string, index: number, unlockScript: string){
        this.txId = txId;
        this.outputIndex = index;
        this.unlockScript = unlockScript;
    }

    // 反序列化,進(jìn)行類(lèi)型轉(zhuǎn)換
    public static createInputsFromUnserialize(objs: Array){
        let ins = [];
        objs.forEach((obj)=>{
            ins.push(new Input(obj.txId,obj.outputIndex,obj.unlockScript));
        });
        return ins;
    }
    
    canUnlock (privateKey: string): boolean{
        if(privateKey == this.unlockScript){
            return true;
        }else{
            return false;
        }
    }
}

私有屬性txId標(biāo)識(shí) “某個(gè)可用的utxo所屬的交易”,是一串sha256編碼的字符串;
outputIndex表示 “這個(gè)可用的utxo在對(duì)應(yīng)交易的序號(hào)值”;
unlockScript則是解鎖腳本,此處并未完全按照BTC的原型去實(shí)現(xiàn),而是簡(jiǎn)單的驗(yàn)證使用者的私鑰來(lái)實(shí)現(xiàn)鑒權(quán),原理上仍遵從BTC的思想。

交易輸出
import * as rsaConfig from "../../rsa.json";
export class Output {
    private value: number;
    // 鎖定腳本,需要使用UTXO歸屬者用私鑰進(jìn)行簽名通過(guò)
    // 當(dāng)解鎖UTXO成功后,此UTXO變?yōu)橄乱粋€(gè)交易的交易輸入,同時(shí)使用接收方的地址(公鑰)鎖定本次交易的交易輸出,
    // 等待接收方使用私鑰簽名使用該UTXO
    // 因此,btc沒(méi)有賬戶的概念,所有的“錢(qián)”由自己的公鑰所加密保存,只有用自己的私鑰才能使用這些錢(qián)(即解鎖了UTXO的解鎖腳本)
    private lockScript: string;

    // 該屬性僅僅在交易時(shí)使用,設(shè)置屬性
    private txId: string;

    // 該屬性僅僅在交易時(shí)使用,設(shè)置屬性
    private index: number;

    public get $index(): number {
        return this.index;
    }

    public set $index(value: number) {
        this.index = value;
    }
    
    public get $txId(): string {
        return this.txId;
    }

    public set $txId(value: string) {
        this.txId = value;
    }
    

    public get $value(): number {
        return this.value;
    }

    public set $value(value: number) {
        this.value = value;
    }

    /* public get $lockScript(): string {
        return this.lockScript;
    }

    public set $lockScript(value: string) {
        this.lockScript = value;
    } */
    
    constructor(value: number,publicKey: string){
        this.value = value;
        this.lockScript = publicKey;
    }

    // 反序列化,進(jìn)行類(lèi)型轉(zhuǎn)換
    public static createOnputsFromUnserialize(objs: Array){
        let outs = [];
        objs.forEach((obj)=>{
            outs.push(new Output(obj.value,obj.lockScript));
        });
        return outs;
    }

    public canUnlock(privateKey: string): boolean{
        if(privateKey == rsaConfig[this.lockScript]){
            return true;
        }else{
            return false;
        }
    }
}

交易輸出中的value屬性標(biāo)識(shí)當(dāng)前utxo的余額,即BTC個(gè)數(shù);
lockScript屬性為鎖定腳本,在我們的簡(jiǎn)易實(shí)現(xiàn)中就為接收方的公鑰,并不是BTC中的逆波蘭式,但大體原理相同,都需要提供私鑰來(lái)進(jìn)行解密。

一筆交易

一筆交易,包含了若干個(gè)交易輸入和交易輸出,同時(shí)也提供了一個(gè)txId唯一的標(biāo)識(shí)這比交易。從結(jié)構(gòu)上看是這樣的:

export class Transaction {
    private txId: string;
    private inputTxs: Array;
    private outputTxs: Array;

    constructor(txId: string, inputs: Array, outputs: Array){
        this.txId = txId;
        this.inputTxs = inputs;
        this.outputTxs = outputs;
    }

    public get $txId(): string {
        return this.txId;
    }

    public set $txId(value: string) {
        this.txId = value;
    }

    public get $inputTxs(): Array {
        return this.inputTxs;
    }

    public set $inputTxs(value: Array) {
        this.inputTxs = value;
    }

    public get $outputTxs(): Array {
        return this.outputTxs;
    }

    public set $outputTxs(value: Array) {
        this.outputTxs = value;
    }
    /* 
        1.交易結(jié)構(gòu)各字段序列化為字節(jié)數(shù)組
        2.把字節(jié)數(shù)組拼接為支付串
        3.對(duì)支付串計(jì)算兩次SHA256 得到交易hash 
    */
    public setTxId(){
        let sha256 = crypto.createHash("sha256");
        sha256.update(JSON.stringify(this.inputTxs) + JSON.stringify(this.outputTxs) + Date.now(),"utf8");
        this.txId = sha256.digest("hex");
    }

}

其中 txId的計(jì)算這里并沒(méi)有嚴(yán)格按照BTC實(shí)現(xiàn)的那樣進(jìn)行計(jì)算,而是簡(jiǎn)單的進(jìn)行對(duì)象序列化進(jìn)行一次sha256。

coinbase交易

我們都知道得到比特幣需要挖礦,其實(shí)挖礦也屬于一種交易,不過(guò)是一種沒(méi)有確定交易輸入的一種交易,它也被稱作coinbase交易。coinbase交易在每一個(gè)區(qū)塊中都會(huì)存在,它的總額包括了系統(tǒng)針對(duì)礦工打包交易過(guò)程的獎(jiǎng)勵(lì)以及其他轉(zhuǎn)賬方提供的手續(xù)費(fèi),如下圖:

因此,創(chuàng)建一個(gè)coinbase交易也很容易

    // coinbase交易用于給礦工獎(jiǎng)勵(lì),input為空,output為礦工報(bào)酬
    public static createCoinbaseTx(pubKey: string, info: string){
        let input = new Input("",-1,info);
        let output = new Output(AWARD, pubKey);
        let tx = new Transaction("",[input],[output])
        tx.setTxId();
        return tx;
    }

在我們的實(shí)現(xiàn)中,只需提供鎖定utxo的公鑰以及一串描述字符串即可,最后設(shè)置交易的txId,完成coinbase交易的創(chuàng)建。

也提供了識(shí)別coinbase交易的方法:

public static isCoinbaseTx(tx: Transaction){
    if(tx.$inputTxs.length == 1 && tx.$inputTxs[0].$outputIndex == -1 && tx.$inputTxs[0].$txId == ""){
        return true;
    }else{
        return false;
    }
}

至此,coinbase交易就完成了,這是最簡(jiǎn)單的一種交易,并沒(méi)有涉及到轉(zhuǎn)賬方,也就是交易輸入。

轉(zhuǎn)賬交易

使用BTC就避免不了轉(zhuǎn)賬,轉(zhuǎn)賬事務(wù)在utxo模型的實(shí)現(xiàn)就是添加了一筆Transaction到某個(gè)區(qū)塊而已。每一筆交易都需要交易輸入和交易輸出,因此在BTC中,轉(zhuǎn)賬的核心就是找到轉(zhuǎn)賬方的utxo進(jìn)行消費(fèi),同時(shí)將指定數(shù)量的BTC劃到指定的消費(fèi)輸出上,如果仍有剩余,則找零至自己的消費(fèi)輸出。

// 創(chuàng)建轉(zhuǎn)賬交易
public static createTransaction(from: string, fromPubkey: string, fromKey: string, to: string, toPubkey: string, coin: number){
    let outputs = this.findUTXOToTransfer(fromKey, coin);
    console.log(`UTXOToTransfer: ${JSON.stringify(outputs)}, from: ${from} to ${to} transfer ${coin}`)
    let inputTx = [], sum = 0, outputTx = [];
    outputs.forEach((o)=>{
        sum += o.$value;
        inputTx.push(new Input(o.$txId,o.$index,fromKey));
    });

    if(sum < coin){
        throw Error(`余額不足,轉(zhuǎn)賬失敗! from ${from} to ${to} transfer ${coin}btc, but only have ${sum}btc`);
    }

    // 公鑰鎖住腳本
    outputTx.push(new Output(coin,toPubkey));
    if(sum > coin){
        outputTx.push(new Output(sum-coin,fromPubkey));
    }
    let tx = new Transaction("",inputTx,outputTx);
    tx.setTxId();
    return tx;
}   

創(chuàng)建一個(gè)交易,需要提供轉(zhuǎn)賬方的地址(公鑰哈希)、轉(zhuǎn)賬方的公鑰和私鑰、接收方的地址、接收方的公鑰以及轉(zhuǎn)賬的BTC數(shù)量。這筆交易由轉(zhuǎn)賬發(fā)發(fā)起,因此需要提供轉(zhuǎn)賬方的私鑰進(jìn)行解鎖腳本。

首先,通過(guò) findUTXOToTransfer 找到滿足轉(zhuǎn)賬數(shù)量的可用的utxo,它需要提供轉(zhuǎn)賬方的私鑰以及轉(zhuǎn)賬數(shù)量;
接下來(lái)根據(jù)獲得的可用utxo,進(jìn)行創(chuàng)建對(duì)應(yīng)的交易輸入;
然后用接收方的公鑰加密交易輸出,同時(shí)如果有余額的化找零給自己,用自己的公鑰加密;
最后根據(jù)得到的交易輸入與交易輸出,創(chuàng)建一筆交易,計(jì)算txId,加入到區(qū)塊中(我們的demo是在單機(jī)下進(jìn)行模擬,并未實(shí)現(xiàn)多播),等待挖礦。

轉(zhuǎn)賬的核心在于 findUTXOToTransfer,在findUTXOToTransfer中,通過(guò)調(diào)用 getAllUnspentOutputTx拿到所有的可用的utxo,并篩選出滿足給定數(shù)量BTC的utxo。

public static getAllUnspentOutputTx(secreteKey: string): Array{
    let outputIndexHash: Object = this.getAllSpentOutput(secreteKey);
    let unspentOutputsTx = [];
    let keys = Object.keys(outputIndexHash);
    let block = BlockDao.getSingletonInstance().getBlock(chain.$lastACKHash);
    while(block && block instanceof Block){
        block.$txs && block.$txs.forEach((tx)=>{
            if(keys.includes(tx.$txId)){
                tx.$outputTxs.forEach((output,i)=>{
                    // 過(guò)濾已消費(fèi)的output
                    if(i == outputIndexHash[tx.$txId])
                        return;
                    
                    if(output.canUnlock(secreteKey)){
                        unspentOutputsTx.push(tx);
                    }    
                });
            }else{
                for(let i=0,len=tx.$outputTxs.length;i

在getAllUnspentOutputTx中,通過(guò) getAllSpentOutput 遍歷本地持久化的區(qū)塊鏈,拿到所有的可供消費(fèi)utxo,這些utxo并不僅僅屬于轉(zhuǎn)賬方,因此需要在針對(duì)每個(gè)utxo嘗試進(jìn)行驗(yàn)證邏輯,即output.canUnlock(secreteKey)。驗(yàn)證通過(guò)則證明這是屬于轉(zhuǎn)賬方的BTC,可以用于交易。

在getAllSpentOutput中,通過(guò)遍歷每一個(gè)交易輸入獲取它指向前面交易的某個(gè)utxo來(lái)得到所有的utxo,當(dāng)然對(duì)于coinbase交易我們無(wú)法找到他的交易輸入,因此會(huì)進(jìn)行過(guò)濾。

至此,utxo的轉(zhuǎn)賬流程已經(jīng)完成,下面需要做的就是把這比交易加入到區(qū)塊中了,這已不是本文的核心。

尾聲

本文所講的utxo示例是基于作者對(duì)BTC實(shí)現(xiàn)的基礎(chǔ)上的簡(jiǎn)單實(shí)現(xiàn),有不當(dāng)之處還請(qǐng)讀者指出。另外,本文的代碼開(kāi)源在 https://github.com/royalrover... 的 feature/utxo分支 上,希望大家一起提建議!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93840.html

相關(guān)文章

  • Node.js買(mǎi)賣(mài)比特 教程

    摘要:完整的步驟如下檢查比特幣或的余額,錢(qián)包地址。比特幣的到帳時(shí)間是個(gè)區(qū)塊的高度,約分鐘。 通過(guò) Nodejs 買(mǎi)賣(mài)Bitcoin showImg(https://segmentfault.com/img/remote/1460000018771566?w=1200&h=659); Github Repo 方案一: 通過(guò)ExinCore API進(jìn)行幣幣交易 Exincore 提供了基于Mix...

    Airy 評(píng)論0 收藏0
  • Nodejs 比特開(kāi)發(fā)教程: 創(chuàng)建比特錢(qián)包

    摘要:下面的代碼,可以讀取比特幣錢(qián)包余額網(wǎng)內(nèi)免手續(xù)費(fèi)的,并且即時(shí)確認(rèn)任何幣在內(nèi)部的交易,都是無(wú)手續(xù)費(fèi)的,并且立刻到賬。 基于Mixin Network的 Nodejs 比特幣開(kāi)發(fā)教程: 創(chuàng)建比特幣錢(qián)包 showImg(https://segmentfault.com/img/remote/1460000018771566?w=1200&h=659);我們已經(jīng)創(chuàng)建過(guò)一個(gè)回復(fù)消息的機(jī)器人和一個(gè)能...

    caozhijian 評(píng)論0 收藏0
  • Python生成以太坊和比特vanity虛榮地址

    摘要:分享一些以太坊比特幣等區(qū)塊鏈相關(guān)的交互式在線編程實(shí)戰(zhàn)教程以太坊,主要是針對(duì)工程師使用進(jìn)行區(qū)塊鏈以太坊開(kāi)發(fā)的詳解。這里是原文如何用為以太坊和比特幣生成虛擬地址 今天,我們將編寫(xiě)一個(gè)非常簡(jiǎn)單的python腳本來(lái)生成虛榮地址,這些地址是以某個(gè)短語(yǔ)或字母序列開(kāi)頭的加密貨幣地址。該過(guò)程涉及生成私鑰并檢查目標(biāo)短語(yǔ)的地址,直到找到滿意的地址。 安裝包 首先,我們需要安裝一些可以執(zhí)行計(jì)算的軟件包,以便...

    MAX_zuo 評(píng)論0 收藏0
  • 如何理解比特和區(qū)塊鏈?

    摘要:比特幣區(qū)塊鏈無(wú)疑是當(dāng)今業(yè)界的最熱門(mén)的。目前,每個(gè)成功的礦工獲得可能每年更換一次或通過(guò)比特幣社區(qū)決策作為成功向區(qū)塊鏈添加一塊交易的獎(jiǎng)勵(lì)。填寫(xiě)其他詳細(xì)信息,例如比特幣金額和可選說(shuō)明。 比特幣區(qū)塊鏈無(wú)疑是當(dāng)今業(yè)界的最熱門(mén)的。通過(guò)這篇博客,我將盡力向大家介紹加密貨幣比特幣的概念,以及它如何創(chuàng)造我們稱之為區(qū)塊鏈的革命性技術(shù)。 這個(gè)問(wèn)題經(jīng)常引起混淆。這篇文章可以快速解釋和清理這方面的混亂! 什么是...

    Kosmos 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<