python数字货币自动交易,python 区块链开发教程

  python数字货币自动交易,python 区块链开发教程

  本文主要为大家介绍一个python区块链简单版事务实现的例子。有需要的朋友可以借鉴一下,希望能有所帮助。祝大家进步很大,早日升职加薪。

  00-1010描述介绍比特币交易输出发送货币余额查看汇总

  

目录

  本文根据https://github.com/liuchengxu/blockchain-tutorial,的内容用python实现,但根据个人理解做了一些修改,并引用了大量原文。文章的最后是“本节中完整源代码实现的地址”。

  

说明

  交易是比特币的核心,区块链的唯一目的就是安全可靠地存储交易。在区块链,交易一旦创建,任何人都不能修改或删除。今天,我们将开始实现交易。不过,既然交易是个大话题,我就分成两部分:今天的部分,我们来认识一下交易的基本框架。在第二部分,我们将继续讨论它的一些细节。

  由于比特币采用的是UTXO模型,而不是账户模型,所以直接没有“余额”的概念,余额需要遍历整个交易历史才能得到。

  

引言

  点击此处查看下图中https://www.blockchain.com/explorer.的交易信息

  交易是一些输入和输出的组合:

  类别交易(对象):

  def __init__(self,vins,vouts):

  self.txid=

  self.vins=vins

  self.vouts=vouts

  对于每一个新的事务,它的输入都会引用上一个事务的输出(这里有一个例外,coinbase事务),引用就是成本。引用以前的输出,即在另一个交易的输入中包含以前的输出,意味着花费以前的交易输出。交易的输出是钱实际存储的地方。下图说明了事务之间的相关性:

  注意:

  一些输出与输入无关。最后一个事务的输入可以参考先前事务的输出。在本文中,输入必须指输出。我们将使用像“钱”、“硬币”、“花费”、“发送”、“账户”等词语。但在比特币中,没有这个概念。事务只通过一个脚本锁定一些值,这些值只能由锁定它们的人解锁。

  每一次比特币交易都会产生一个输出,这个输出会被区块链记录下来。给某人发送比特币,实际上就是创建一个新的UTXO,注册到那个人的地址,可以被他使用。

  

比特币交易

  从输出开始:

  TXOutput类(对象):

  def __init__(self,value,script_pub_key):

  自我价值=价值

  self . script _ pub _ key=script _ pub _ key

  输出主要由两部分组成:

  一定数量的比特币(价值)

  锁定的脚本(script_pub_key)。要花这笔钱,剧本必须解锁。

  实际上,是输出存储了“货币”(注意,就是上面的值字段)。这里的存储是指用一个数学难题锁定输出,存储在script_pub_key中。在内部,比特币使用一种叫做Script的脚本语言来定义锁定和解锁输出的逻辑。虽然这种语言相当原始(这是为了避免潜在的黑客攻击和滥用而故意的),也不复杂,但我们在这里不讨论它的细节。你可以在这里找到详细解释。

  在比特币中,价值域存储sat。

  oshi 的数量,而不是 BTC 的数量。一个 satoshi 等于一亿分之一的 BTC(0.00000001 BTC),这也是比特币里面最小的货币单位(就像是 1 分的硬币)。

  由于还没有实现地址(address),所以目前我们会避免涉及逻辑相关的完整脚本。script_pub_key 将会存储一个任意的字符串(用户定义的钱包地址)。

  顺便说一下,有了一个这样的脚本语言,也意味着比特币其实也可以作为一个智能合约平台。

  关于输出,非常重要的一点是:它们是不可再分的(indivisible)。也就是说,你无法仅引用它的其中某一部分。要么不用,如果要用,必须一次性用完。当一个新的交易中引用了某个输出,那么这个输出必须被全部花费。如果它的值比需要的值大,那么就会产生一个找零,找零会返还给发送方。这跟现实世界的场景十分类似,当你想要支付的时候,如果一个东西值 1 美元,而你给了一个 5 美元的纸币,那么你会得到一个 4 美元的找零。

  

  

发送币

  现在,我们想要给其他人发送一些币。为此,我们需要创建一笔新的交易,将它放到一个块里,然后挖出这个块。之前我们只实现了 coinbase 交易(这是一种特殊的交易),现在我们需要一种通用的普通交易:

  

def new_transaction(self, from_addr, to_addr, amount):

   inputs = []

   outputs = []

   acc, valid_outpus = self._find_spendable_outputs(from_addr, amount)

   if acc < amount:

   raise NotEnoughAmountError(unot enough coin)

   for txid, outs in valid_outpus.items():

   for out in outs:

   out_index = out[0]

   input = TXInput(txid, out_index, from_addr)

   inputs.append(input)

   output = TXOutput(amount, to_addr)

   outputs.append(output)

   if acc > amount:

   # a change

   outputs.append(TXOutput(acc - amount, from_addr))

   tx = Transaction(inputs, outputs)

   tx.set_id()

   return tx

  

  在创建新的输出前,我们首先必须找到所有的未花费输出,并且确保它们有足够的价值(value),这就是 _find_spendable_outputs 方法要做的事情。随后,对于每个找到的输出,会创建一个引用该输出的输入。接下来,我们创建两个输出:

  一个由接收者地址锁定。这是给其他地址实际转移的币。

  一个由发送者地址锁定。这是一个找零。只有当未花费输出超过新交易所需时产生。记住:输出是不可再分的。

  这个方法对所有的未花费交易进行迭代,并对它的值进行累加。当累加值大于或等于我们想要传送的值时,它就会停止并返回累加值,同时返回的还有通过交易 ID 进行分组的输出索引。我们只需取出足够支付的钱就够了。

  现在我们修改add_block方法:

  

 def add_block(self, transactions):

   """

   add a block to block_chain

   """

   last_block = self.get_last_block()

   prev_hash = last_block.get_header_hash()

   height = last_block.block_header.height + 1

   block_header = BlockHeader(, height, prev_hash)

   block = Block(block_header, transactions)

   block.mine()

   block.set_header_hash()

   self.db.create(block.block_header.hash, block.serialize())

   last_hash = block.block_header.hash

   self.set_last_hash(last_hash)

  

  最后,让我们来实现 send 方法:

  

def send(bc, from_addr, to_addr, amount):

   bc = BlockChain()

   tx = bc.new_transaction(from_addr, to_addr, amount)

   bc.add_block([tx])

   print(send %d from %s to %s %(amount, from_addr, to_addr))

  

  发送币意味着创建新的交易,并通过挖出新块的方式将交易打包到区块链中。不过,比特币并不是一连串立刻完成这些事情(虽然我们目前的实现是这么做的)。相反,它会将所有新的交易放到一个内存池中(mempool),然后当矿工准备挖出一个新块时,它就从内存池中取出所有交易,创建一个候选块。只有当包含这些交易的块被挖出来,并添加到区块链以后,里面的交易才开始确认。

  让我们来检查一下发送币是否能工作:

  首先我们要执行main.py完成创世块的构建

  

$ python3 main.py

  Mining a new block

  Found nonce == 17ash_hex == 01ded3ff2872093f2eefcd7b8b5b264e96996f31f933e6636db034b4151b61aa

  Block(_block_header=BlockHeader(timestamp=1551086196.4749706, hash_merkle_root=, prev_block_hash=, hash=ce93f6e1a2f7dec3a538e8b6397e4b8eba59bace2e7ac08f82875447d2660173, nonce=None, height=0))

  Block(_block_header=BlockHeader(timestamp=1551086196.6248493, hash_merkle_root=, prev_block_hash=, hash=d5ecad2ed10a978e2f280e62d6a25ce4def6cdfc66ac9dcd124c24c5a4b9ac07, nonce=17, height=1))

  

  

$ python3 cli.py send --from zhangsanaddr --to lisiaddr --amount 10

  Found nonce == 0ash_hex == 08c67066d0c7fc8d2ef80076e91626ff05999046ae0248e1971b99a30541518b

  send 10 from zhangsanaddr to lisiaddr

  

  

  

余额查看

  

def get_balance(bc, addr):

   balance = 0

   utxos = bc.find_UTXO(addr)

   for utxo in utxos:

   balance += utxo.value

   print(%s balance is %d %(addr, balance))

  

  find_UTXO方法找出所有的UTXO,实现如下:

  

$ python3 cli.py balance zhangsanaddr 

  zhangsanaddr balance is 980

  

  先利用_find_unspent_transactions找出所有的未花费交易,并判断是否是当前地址可以解锁的,就找出了所有的UTXO。

  测试一下效果:

  

$ python3 cli.py balance zhangsanaddr 

  zhangsanaddr balance is 980

  

  

  

总结

  虽然不容易,但是现在终于实现交易了!不过,我们依然缺少了一些像比特币那样的一些关键特性:

  地址(address)。我们还没有基于私钥(private key)的真实地址。

  奖励(reward)。现在挖矿是肯定无法盈利的!

  UTXO 集。获取余额需要扫描整个区块链,而当区块非常多的时候,这么做就会花费很长时间。并且,如果我们想要验证后续交易&#xff0c;也需要花费很长时间。而 UTXO 集就是为了解决这些问题,加快交易相关的操作。

  内存池(mempool)。在交易被打包到块之前,这些交易被存储在内存池里面。在我们目前的实现中,一个块仅仅包含一笔交易,这是相当低效的。

  参考:

  [1] https://github.com/liuchengxu/blockchain-tutorial/blob/master/content/part-4/transactions-1.md

  [2] 本节完整实现源码

  以上就是python区块链简易版交易实现示例的详细内容,更多关于python区块链交易的资料请关注盛行IT软件开发工作室其它相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: