GO语言实现区块链-coinbase交易1

197 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

coinbase交易

什么是coinbase交易

coinbase交易一般是指矿工挖矿的奖励,也就是说,其没有输入项,只有输出项,且输出来自系统奖励。

如何判断Coinbase交易

首先考虑函数参数问题,由于是属于系统奖励、因此只考虑接收方就可以。但是我们作为开发人员,好歹也要“露个面”。

//创建CoinBase交易
func NewCoinbaseTX(to, data string) *Transaction {
	if data == "" {
		data = fmt.Sprintf("Reward to '%s'", to)
	}
	//创建一个输入项
	txin := TXInput{[]byte{}, -1, nil, []byte(data)}
	//创建输出项
	txout := NewTXOutput(subsidy, to)
	tx := Transaction{nil, []TXInput{txin}, []TXOutput{*txout}}
	tx.SetID()

	return &tx
}

coinbase的判断方法

在确定了CoinBase后,我们也可以清晰的判断出什么是coinbase交易了。该输入项的切片只有一个元素,该元素Voutx为-1,并且输出项切片只有一个元素。


//是否为CoinBase交易
func (tx Transaction) IsCoinbase() bool {
	return len(tx.Vin) == 1 &&
		len(tx.Vin[0].Txid) == 0 &&
		tx.Vin[0].VoutIdx == -1
}

如何使用coinbase交易

  • 1、修改NewBlock函数,奖原Data域替换为[]*Transaction类型。
  • 2、修改ProofOfWork的prepareData和Run方法,将原Data域调整。
  • 3、修改创世块创建函数,原Data域替换为Coinbase交易
  • 4、修改NewBlockchain函数,创世块创建部分调整
  • 5、main函数调用调整。

下面,我们对主要修改的地方做一个详细讲解:

1、修改NewBlock函数,只涉及传入参数与对象构造方面。

// 创建Block,返回Block指针
func NewBlock(txs []*Transaction, prevBlockHash []byte) *Block {
	//先构造block
	block := &Block{time.Now().Unix(), txs, prevBlockHash, []byte{}, 0}
	//需要先挖矿
	pow := NewProofOfWork(block)
	nonce, hash := pow.Run()
	//设置hash和nonce
	block.Hash = hash
	block.Nonce = nonce
	return block
}

2、修改pow.go文件。pow.go的修改主要是受Block结构变化的影响。

func (pow *ProofOfWork) prepareData(nonce int64) []byte {
	data := bytes.Join(
		[][]byte{
			pow.block.PrevBlockHash,
			pow.block.HashTransactions(),
			Int2Hex(pow.block.Timestamp),
			Int2Hex(int64(targetBits)),
			Int2Hex(nonce),
		},
		[]byte{},
	)

	return data
}

run函数主要代码:

fmt.Printf("%s\n", pow.block.Transactions[0].Vin[0].FromAddr)