以太坊微支付通道原理与实现

2023-11-04

以太坊微支付通道原理与实现

线上直接转账需要一定的费用,如果存在大量小额交易的情况下,费用会变的难以承受,因而以太坊引入了微交易支付通道来解决这个问题。以太坊提供了一个票据支付方案,主要依赖于智能合约实现的一对多的账单系统。该账单系统大致上的执行流程如下.

  • 1:账单生成,同时提供机制往账单上存入保证金。

  • 2:交易发起人生成交易票据

  • 3:直接将票据发送给接收人

  • 4:接收人兑现票据,从合约转账(尽管某次兑现可能会失败,但是只要票据存在最终还是能够兑现).

这种交易优点在于可以在线下发送任意数量的交易,而只需要两个链上交易(存入保证金,兑现)只要存入保证金,线下通过交换票据进行任意数量的交易,避免了频繁的线上转账,节省了交易费用。

代码结构

.
├── api.go                             //对外接口
├── cheque.go                          //账单
├── cheque_test.go
├── contract       
│   ├── chequebook.go                  //合约go语言接口
│   ├── chequebook.sol                 //合约源码
│   ├── code.go                        //合约byte码
│   ├── mortal.sol                     //合约销毁
│   └── owned.sol                      //hebe权限
└── gencode.go                         //合约byte码生成

合约层

合约自身是接收转账的,用户可以在初始化或者后来增加金额,可以通过cash方法兑现票据,转账金额都会保存在send变量上。

    pragma solidity ^0.4.18;

    import "./mortal.sol";

    /// @title Chequebook for Ethereum micropayments
    /// @author Daniel A. Nagy <daniel@ethereum.org>
    contract chequebook is mortal {
        // Cumulative paid amount in wei to each beneficiary
        //已经支付的 可以控制双花,防止多次兑换票据
        mapping (address => uint256) public sent;

        /// @notice Overdraft event
        event Overdraft(address deadbeat);

        // Allow sending ether to the chequebook.
        function() public payable { }

        /// @notice Cash cheque
        ///
        /// @param beneficiary beneficiary address
        /// @param amount cumulative amount in wei
        /// @param sig_v signature parameter v
        /// @param sig_r signature parameter r
        /// @param sig_s signature parameter s
        /// The digital signature is calculated on the concatenated triplet of contract address, beneficiary address and cumulative amount
        function cash(address beneficiary, uint256 amount, uint8 sig_v, bytes32 sig_r, bytes32 sig_s) public {
            // Check if the cheque is old.
            // Only cheques that are more recent than the last cashed one are considered.
            require(amount > sent[beneficiary]);
            // Check the digital signature of the cheque.
            bytes32 hash = keccak256(address(this), beneficiary, amount);
            require(owner == ecrecover(hash, sig_v, sig_r, sig_s));
            // Attempt sending the difference between the cumulative amount on the cheque
            // and the cumulative amount on the last cashed cheque to beneficiary.
            uint256 diff = amount - sent[beneficiary];
            if (diff <= this.balance) {
                // update the cumulative amount before sending
                sent[beneficiary] = amount;
                beneficiary.transfer(diff);
            } else {
                // Upon failure, punish owner for writing a bounced cheque.
                // owner.sendToDebtorsPrison();
                Overdraft(owner);
                // Compensate beneficiary.
                selfdestruct(beneficiary);
            }
        }
    }

支付层

账单保存了账本的位置,记账人,所有人等信

    // Chequebook can create and sign cheques from a single contract to multiple beneficiaries.
    // It is the outgoing payment handler for peer to peer micropayments.
    type Chequebook struct {
        path     string                      // path to chequebook file
        prvKey   *ecdsa.PrivateKey           // private key to sign cheque with
        lock     sync.Mutex                  //
        backend  Backend                     // blockchain API
        quit     chan bool                   // when closed causes autodeposit to stop
        owner    common.Address              // owner address (derived from pubkey)
        contract *contract.Chequebook        // abigen binding
        session  *contract.ChequebookSession // abigen binding with Tx Opts

        // persisted fields
        balance      *big.Int                    // not synced with blockchain
        contractAddr common.Address              // contract address
        sent         map[common.Address]*big.Int //tallies for beneficiaries

        txhash    string   // tx hash of last deposit tx
        threshold *big.Int // threshold that triggers autodeposit if not nil
        buffer    *big.Int // buffer to keep on top of balance for fork protection

        log log.Logger // contextual logger with the contract address embedded
    }

票据:合约位置,接收人,金额,签名

    type Cheque struct {
        Contract    common.Address // address of chequebook, needed to avoid cross-contract submission
        Beneficiary common.Address
        Amount      *big.Int // cumulative amount of all funds sent
        Sig         []byte   // signature Sign(Keccak256(contract, beneficiary, amount), prvKey)
    }

票据生成

生成一条支付记录,返回一份签名后的票据,收费这凭借这张票据从合约里面取钱.

    // Issue creates a cheque signed by the chequebook owner's private key. The
    // signer commits to a contract (one that they own), a beneficiary and amount.
    func (self *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *Cheque, err error) {
        defer self.lock.Unlock()
        self.lock.Lock()

        if amount.Sign() <= 0 {
            return nil, fmt.Errorf("amount must be greater than zero (%v)", amount)
        }
        if self.balance.Cmp(amount) < 0 {
            err = fmt.Errorf("insufficient funds to issue cheque for amount: %v. balance: %v", amount, self.balance)
        } else {
            var sig []byte
            sent, found := self.sent[beneficiary]
            if !found {
                sent = new(big.Int)
                self.sent[beneficiary] = sent
            }
            sum := new(big.Int).Set(sent)
            sum.Add(sum, amount)

            sig, err = crypto.Sign(sigHash(self.contractAddr, beneficiary, sum), self.prvKey)
            if err == nil {
                ch = &Cheque{
                    Contract:    self.contractAddr,
                    Beneficiary: beneficiary,
                    Amount:      sum,
                    Sig:         sig,
                }
                sent.Set(sum)
                self.balance.Sub(self.balance, amount) // subtract amount from balance
            }
        }

        // 账单余额少于阈值,自动补充.
        if self.threshold != nil {
            if self.balance.Cmp(self.threshold) < 0 {
                send := new(big.Int).Sub(self.buffer, self.balance)
                self.deposit(send)
            }
        }

        return
    }

存储金额

    func (self *Chequebook) Deposit(amount *big.Int) (string, error) {
        defer self.lock.Unlock()
        self.lock.Lock()
        return self.deposit(amount)
    }

    func (self *Chequebook) deposit(amount *big.Int) (string, error) {
        // since the amount is variable here, we do not use sessions
        depositTransactor := bind.NewKeyedTransactor(self.prvKey)
        depositTransactor.Value = amount
        chbookRaw := &contract.ChequebookRaw{Contract: self.contract}
        //转入金额
        tx, err := chbookRaw.Transfer(depositTransactor)
        if err != nil {
            self.log.Warn("Failed to fund chequebook", "amount", amount, "balance", self.balance, "target", self.buffer, "err", err)
            return "", err
        }
        // assume that transaction is actually successful, we add the amount to balance right away
        self.balance.Add(self.balance, amount)
        self.log.Trace("Deposited funds to chequebook", "amount", amount, "balance", self.balance, "target", self.buffer)
        return tx.Hash().Hex(), nil
    }

兑换票据

// Cash is a convenience method to cash any cheque.
func (self *Chequebook) Cash(ch *Cheque) (txhash string, err error) {
	return ch.Cash(self.session)
}

// Cash cashes the cheque by sending an Ethereum transaction.
func (self *Cheque) Cash(session *contract.ChequebookSession) (string, error) {
	v, r, s := sig2vrs(self.Sig)
    //调用合约的cash方法 提取代币
	tx, err := session.Cash(self.Beneficiary, self.Amount, v, r, s)
	if err != nil {
		return "", err
	}
	return tx.Hash().Hex(), nil
}

其他接口

OutBox:用于在电对点网络中发行票据,提供了保证金存入,票据发行,自动存入保证金等接口。

    type Outbox struct {
        chequeBook  *Chequebook
        beneficiary common.Address
    }

    // Issue creates cheque.
    func (self *Outbox) Issue(amount *big.Int) (swap.Promise, error) {
        return self.chequeBook.Issue(self.beneficiary, amount)
    }

    // AutoDeposit enables auto-deposits on the underlying chequebook.
    func (self *Outbox) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) {
        self.chequeBook.AutoDeposit(interval, threshold, buffer)
    }

InBox:用于在电对点网络中票据兑换,提供了直接兑换,定时兑换,延迟兑换的接口功能。

    // Inbox can deposit, verify and cash cheques from a single contract to a single
    // beneficiary. It is the incoming payment handler for peer to peer micropayments.
    type Inbox struct {
        lock        sync.Mutex
        contract    common.Address              // peer's chequebook contract
        beneficiary common.Address              // local peer's receiving address
        sender      common.Address              // local peer's address to send cashing tx from
        signer      *ecdsa.PublicKey            // peer's public key
        txhash      string                      // tx hash of last cashing tx
        session     *contract.ChequebookSession // abi contract backend with tx opts
        quit        chan bool                   // when closed causes autocash to stop
        maxUncashed *big.Int                    // threshold that triggers autocashing
        cashed      *big.Int                    // cumulative amount cashed
        cheque      *Cheque                     // last cheque, nil if none yet received
        log         log.Logger                  // contextual logger with the contract address embedded
    }

    // Cash attempts to cash the current cheque.
    func (self *Inbox) Cash() (txhash string, err error) {
        if self.cheque != nil {
            txhash, err = self.cheque.Cash(self.session)
            self.log.Trace("Cashing in chequebook cheque", "amount", self.cheque.Amount, "beneficiary", self.beneficiary)
            self.cashed = self.cheque.Amount
        }
        return
    }

转自:(魂祭心) https://my.oschina.net/hunjixin/blog/1807446

如果你希望高效的学习以太坊DApp开发,可以访问汇智网提供的最热门在线互动教程:

1.适合区块链新手的以太坊DApp实战入门教程
2.区块链+IPFS+Node.js+MongoDB+Express去中心化以太坊电商应用开发实战

其他更多内容也可以访问这个以太坊博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以太坊微支付通道原理与实现 的相关文章

  • NFTScan 与 Atem Network 在 NFT 数据领域达成战略合作

    近日 Web3 基础设施 NFTScan 浏览器与 Atem Network 协议达成战略合作伙伴关系 双方已在 NFT 数据领域展开深度了合作 Atem Network 是一个 Web3 社交平台 用户可以通过 NFT 创建 连接和拥有自
  • infura上部署以太坊智能合约

    Infura是一个托管的以太坊节点集群 可以将你开发的以太坊智能合约发布到infura提供的节点上 而无需搭建自己的以太坊节点 可能你还不了解Infura 但如果你使用过MetaMask 那么就已经接触过Infura了 因为它是MetaMa
  • 测试中

    root ubu blockchain2 ll total 44 drwx 5 root root 4096 Aug 4 09 48 drwxr xr x 23 root root 4096 Jul 26 11 26 rw r r 1 ro
  • Flashswap 学习笔记(附代码)

    什么是Flashswap 利用交易的原子性 可以在这样的同一笔交易中调用智能合约 同时完成借和还 参考下图 Flashswap流程 代码 流程 代码 SPDX License Identifier GPL 3 0 pragma solidi
  • 以太坊学习笔记:私有链搭建操作指南

    原文链接 https my oschina net u 2349981 blog 865256 讲解的内容非常详细 熟悉搭建以太坊私有链的相关操作 学习了 摘要 详解以太坊私有链搭建过程以及一些常用的操作 虽然以太坊是一个公有链系统 但是我
  • web3.js

    安装 别按照官网上面 npm install web3 下载 我已经吃过一次亏了 npm init npm install ethereum web3 js save 指令 web3 isConnected 检查结点的连接是否存在 web3
  • 以太坊的状态树 Merkle Patricia Tree

    Merkle Patricia Tree Merkle树 https www cnblogs com fengzhiwu p 5524324 html Merkle Tree 通常也被称作Hash Tree 顾名思义 就是存储hash值的一
  • 区块链学习笔记13——ETH以太坊概述

    区块链学习笔记13 ETH以太坊概述 学习视频 北京大学肖臻老师 区块链技术与应用 笔记参考 北京大学肖臻老师 区块链技术与应用 公开课系列笔记 目录导航页 比特币和以太坊是两种最主要的加密货币 比特币被称为区块链1 0 以太坊被称为区块链
  • 以太坊nonce详解

    文章目录 1 nonce 是什么 2 如何使用 nonce 3 加速和取消以太坊的交易 4 异常处理 5 nonce 使用的几条规则 6 参考资料 1 nonce 是什么 A scalar value equal to the number
  • JAVA 使用web3j接入以太坊(一)

    第一步先创建maven项目 在项目的pom文件依赖中添加web3j
  • truffle教程

    直接在geth的控制台通过solc进行编译部署的示例已经很多了 比如这篇博客 此处不再赘述 本文主要演示怎样通过truffle部署以太坊智能合约 truffle是一个以太坊智能合约开发框架 它会帮你做很多琐碎的事情 安装使用都很简单 1 安
  • 通过python构建一个区块链来学习区块链

    了解区块链Blockchains如何工作的最快方法就是构建一个区块链 你来到这里是因为 和我一样 你对加密钱币的崛起感到很兴奋 而且你想知道区块链是如何工作的 想了解它们背后的基本技术 但理解区块链并不容易 或者至少不适合我 我在密集的视频
  • 如何通过Geth、Node.js和UNIX/PHP访问以太坊节点

    本文旨在说明通过Geth Node js如何访问以太坊节点和UNIX下PHP如何访问以太坊节点 说明如何通过RPC使用此 A 以太坊节点 对于以太坊主网络使用RPC url http 85 214 51 53 8545 对于Ropsten测
  • 区块链学习笔记16——以太坊中的交易树和收据树

    十六 以太坊中的交易树和收据树 每次发布一个交易的时候 那些交易会组织成一个交易树 也是一颗Merkle tree跟比特币中的情况是类似的 同时以太坊还增加了一个收据树 每个交易执行完之后会形成一个收据 记录这个交易的相关信息 交易树和收据
  • nodejs以太坊Dapp开发中文资料收集(精选版)

    区块链技术是趋势 会Nodejs 想做区块链相关 选择了以太坊这个平台 网上资料虽然多少能搜到 但是鱼龙混杂 重复错误百出 不够系统 在几天的搜寻筛选之后 整理了以下中文以太坊智能合约开发资料 有不足或者补充的请留言 互相交流共同进步 1
  • UPnP的介绍和理解

    在远程服务器开了一个节点B 然后在自己电脑上启动两个节点A C 用了 bootnodes B命令 A和C都能把B节点添加到自己的列表里 但是A和C不能互相发现是为什么 按理来说B应该把自己知道的节点列表都告诉给他相连的节点吧 答案是 它们会
  • EOS智能合约安全开发终极指南

    EOS智能合约安全终极指南 当世界上最大的ICO EOS于2018年6月推出时 加密社区变得持怀疑态度 并且由于软件错误而被冻结了2天 但快进4个月 EOS今天占了以太网今天所做交易的两倍以上 通过免费和更快速交易的承诺 EOS最顶级的Da
  • Sidetree - 去中心化身份管理协议

    身份 Identity 管理是区块链应用的核心元素 在一个不可信 匿名的分布计算生态中 要实现去中心化身份管理并不是一件容易的事情 Sidetree是一个基于现有区块链平台的第二层 L2s 协议 专门用于去中心化身份管理 微软最新开源的IO
  • 引介

    转载自 https ethfans org posts rlp encode and decode RLP编码和解码 RLP Recursive Length Prefix 递归的长度前缀 是一种编码规则 可用于编码任意嵌套的二进制数组数据
  • 自己动手部署以太坊联盟链

    一个区块链学习项目 GitHub https github com xianfeng92 Love Ethereum 假设已经在Ubunbu 14 04 LTS上安装好了以太坊客户端Geth 使用Geth部署以太坊联盟链 以太坊Geth客户

随机推荐

  • 计算机毕设大作业《基于SpringBoot的实验室管理系统》

    项目背景 社会的发展和科学技术的进步 互联网技术越来越受欢迎 网络计算机的生活方式逐渐受到广大人民群众的喜爱 也逐渐进入了每个用户的使用 互联网具有便利性 速度快 效率高 成本低等优点 因此 构建符合自己要求的操作系统是非常有意义的 本文从
  • mysql数据库基本知识

    本篇笔记主要是总结整理mysql数据库基本知识 需要掌握的主要包括通过信息 gt 画出ER图 gt 由ER图创建数据库表 sql语句 1 概念模型 ER图 图片修改为 2 用sql语句 实现增删查改建等操作 1 建 CREATE TABLE
  • python float转str_python 数据类型互相转换

    关注本号 教你更多python知识 python中 有6种数据类型 那它们之间能不能互相转换 怎样转换 这篇就来说说 数据类型之间的转换 数据类型之间的转换 主要有以下函数 1int 将其它类型转为整型 int x 0 gt integer
  • centos7 下载安装pycharm以及破解

    下载 wget P root opt https download jetbrains com python pycharm professional 2019 1 3 tar gz 解压 cd root opt tar xzvf pych
  • 前端---【nodejs的介绍与Buffer缓冲器的介绍】

    目录 一 node js的介绍 1 1node js是什么 1 2node js的作用 二 运行node js文件 三 buffer 缓冲器 3 1 buffer介绍 3 2特点 3 3创建Buffer的四种方式 3 1创建Buffer第一
  • virt-install: 未找到命令...

    root localhost t virt install bash virt install 未找到命令 yum install libguestfs tools yum install virt install noarch
  • blender简单骨骼绑定

    blender2 90 1 设置3D游标 shift 鼠标右键设置到想要的位置 或者设置到原点 shift s gt Cursor to world origin 或者shift c 2 创建测试的物体 一个长方形 shift a mesh
  • 《UnityAPI.AnimatorStateInfo动画器状态信息》(Yanlz+Unity+SteamVR+云技术+5G+AI+VR云游戏+IsName+IsTag+tag+立钻哥哥++OK++)

    UnityAPI AnimatorStateInfo动画器状态信息 版本 作者 参与者 完成日期 备注 UnityAPI AnimatorStateInfo V01 1 0 严立钻 2020 07 02 UnityAPI AnimatorS
  • 数据结构-链栈的c++实现

    pragma once ifndef My Head H define My Head H include G code c myhead h endif My Head H template
  • 远心镜头的区别

    文章预览 前言 Introduction 物方远心镜头 Object Space Telecentric 像方远心镜头 Image Space Telecentric 双侧远心镜头 Bi Telecentric 总结 Summary 前言
  • Python VTK 球体贴图代码详解(二)

    效果 继昨天的柱体代码学习 之后尝试了一把球体并进行贴图 效果如下 代码 代码是在昨天柱体基础上修改成球体 并针对球体贴图多了两步 import vtk 柱体 生成一个球体 sphere vtk vtkSphereSource 半径 sph
  • 主动运维管理摆脱“救火式”运维局面

    云呐运维管理模块是以服务目录的形式提供IT服务的交付 用户可点击服务目录中的服务 创建请求流程 通过服务门户汇总所有服务请求 事件 问题 变更记录 分派服务任务 监督执行情况全面管控事件的生命周期 支持事件升级策略定义 提高运维人员的效率
  • Linux 中宝塔面板的 tomcat 重启弹窗一闪而过,但是并未启动tomcat的问题

    这几天不知道是项目出错的原因还是其他因素 我在部署项目的时候 好像在宝塔的tomcat管理界面 点击了停止 我本想暂停tomcat服务 之后想再次开启的时候 tomcat 的重启按钮 一点 基本就是瞬间成功 这肯定有问题 一般来说tomca
  • 高校软件工程期末复习——ICONIX

    ch01 软件工程危机 定义 软件在开发和维护过程中遇到的一系列严重的问题 含义 如何开发软件 如何维护数量不断膨胀的已有软件 原因 客户对软件需求的描述不精确 可能有遗漏 有二义性 有错误 在软件开发过程中 用户提出修改软件功能 界面 支
  • Cookie和Session是什么?它们的区别是什么?

    什么是Cookie Cookie实际上是一小段的文本信息 客户端请求服务器 如果服务器需要记录该用户状态 就使用response向客户端浏览器颁发一个Cookie 客户端会把Cookie保存起来 当浏览器再请求该网站时 浏览器把请求的网址连
  • 谷歌浏览器报错:NET::ERR_CERT_AUTHORITY_INVALID

    chrome net internals hsts
  • Vivado使用心得(六)Vivado ILA观察信号和调试过程

    先简单介绍一下ILA Integrated Logic Analyzer 生成方法 这里有两种办法完成Debug Core的配置和实现 方法一 mark debug综合选项 Set Up Debug设定ILA参数 1 在信号 reg或者wi
  • MV-YOLO翻译(2018年5月 CVPR论文)【原创】

    声明 作者翻译论文仅为学习 如有侵权请联系作者删除博文 谢谢 另 如有不当的地方 请各位大佬批评指正 谢谢 MV YOLO 通过语义目标检测实现运动矢量跟踪 原论文pdf下载地址 https arxiv org pdf 1805 00107
  • office2010 错误1706 解决办法

    office2010 错误1706 解决办法 问题描述 1 弹窗 无限弹窗 无限 困扰了我大概半年的问题 自从上次不小心删掉一些有关office2010的东西 导致网页中下载东西后总是弹窗 office2010 卸载出现 安装程序找不到Pr
  • 以太坊微支付通道原理与实现

    以太坊微支付通道原理与实现 线上直接转账需要一定的费用 如果存在大量小额交易的情况下 费用会变的难以承受 因而以太坊引入了微交易支付通道来解决这个问题 以太坊提供了一个票据支付方案 主要依赖于智能合约实现的一对多的账单系统 该账单系统大致上