No.3-区块链ETH之golang调用实践

作者: 太白菜Rennbon | 来源:发表于2019-03-29 01:22 被阅读45次

    前言

    eth身为区块链的老二哥,对于技术人而言也是一个必须了解的项目,这里就对geth如何使用二次开发做一个技术性的介绍

    私链部署

    首先,如果要开发一个钱包功能,那么必不可少的,得有一个测试环境能够供自己使用,eth也有官方测试链,但是凡事总是自己的才是最方便的,所以这里我们自己部署一个私链。

    ububtu 安装

    apt-get install software-properties-common
    add-apt-repository -y ppa:ethereum/ethereum
    apt-get update
    apt-get install ethereum
    

    mac安装

    brew tap ethereum/ethereum
    brew install ethereum
    

    配置文件

    genesis.json

    {
        "config": {
            "chainId": 999,
            "homesteadBlock": 0,
            "eip155Block": 0,
            "eip158Block": 0
        },
        "coinbase" : "0x0000000000000000000000000000000000000000",
        "difficulty" : "0x40000",
        "extraData" : "",
        "gasLimit" : "0xffffffff",
        "nonce" : "0x0000000000000042",
        "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
        "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
        "timestamp" : "0x00",
        "alloc": { }
    }
    

    启动私链

    #创建私链
    geth --datadir mychain init genesis.json
    #登录私链
    geth --datadir mychain --networkid 999 --rpc console
    #创建用户
    personal.newAccount()
    #启动挖矿(x是启动几个核心来挖矿)
    miner.start(x) 
    

    以上是基本的操作,具体详细的内容可以网上翻看别人的帖子,这里不做介绍,当然为了开发方便,我们需要结合eth钱包的界面化工具,这样可以让我的操作性大大提升

    eth钱包

    https://github.com/ethereum/mist

    钱包关联私链

    "/Applications/Ethereum Wallet.app/Contents/MacOS/Ethereum Wallet" --rpc /指自定义路径/geth/mychain/geth.ipc
    

    注意路径,以上命令执行成功后,那么eth私链的可视化界面工具就完成了,可以愉快的开发个性功能了

    eth 币种概念

    1. eth 有主链币和代币之分,主链币用于支付交易手续费等
    2. erc20代币,智能合约功能的副产品,是ico更加容易,这也是eth能流行起来的一个依据

    geth 概念分析

    首先我们需要能够区分主链币和代币的概念,对于erc20代币,我们需要根据abi来完成一系列的操作,虽然geth库有提供很完善的token封装,但是对于需要多链集成的框架而言,他太全面了,太强大了,太有个性了反而不能容于集体,所以这里我是直接用abi来完成一些列的操作,
    同时也将eth主链币和erc20代币区分为2种币种,这样能更好的抽象我们自己的框架。

    代币和主链币单位如何维护

    因为代币的单位可以自定义,所以不同的代币他们之间的精确度都会不一样,这也给共同的框架带来了复杂度,我们需要增加一个币种单位管理包来解耦币种单位的差异

    代币转账及离线签名

    对于代币而言,我们能更全面的控制到他的生成及签名的解耦,那就可以更好的做到定制化,以下是boxwallet钱包库代码

    //创建erc20交易
    func (c *Erc20Client) CreateTx(addrsFrom []string, token string, addrsTo []*bccoin.AddressAmount, feeCeo float64) (txu signature.TxUtil, err error) {
        if len(addrsTo) != 1 || len(addrsFrom) != 1 {
            return nil, errors.ERR_PARAM_NOT_VALID
        }
        local, err := c.ChooseClientNode()
        if err != nil {
            return nil, err
        }
        ctx := context.TODO()
        contract := common.HexToAddress(token)
        if err != nil {
            return nil, err
        }
        to := addrsTo[0]
        toAddress := common.HexToAddress(to.Address)
        fromAccDef := accounts.Account{
            Address: common.HexToAddress(addrsFrom[0]),
        }
            //获取erc20代币余额
        tbalance, err := c.GetBalance(addrsFrom[0], token, local)
        if err != nil {
            return nil, err
        }
        cmp, err := tbalance.Cmp(to.Amount)
        if err != nil {
            return nil, err
        }
        if cmp < 0 {
            return nil, errors.ERR_NOT_ENOUGH_COIN
        }
        gasprice, err := c.nmap[local].C.SuggestGasPrice(ctx)
        if err != nil {
            gasprice = c.DefGasPrice
        }
        //contract/abi
            //获取即时Nonce值
        nonce, _ := c.nmap[local].C.NonceAt(ctx, fromAccDef.Address, nil)
            //构建代币data需要的input
        input, err := c.ABI.Pack("transfer", toAddress, to.Amount.Val())
        if err != nil {
            return nil, err
        }
        msg := ethereum.CallMsg{From: fromAccDef.Address, To: &contract, Value: big.NewInt(0), Data: input}
        gasLimit, err := c.nmap[local].C.EstimateGas(ctx, msg)
        if err != nil {
            gasLimit = c.DefGasLimit
        }
    
        excessCeo := (feeCeo - 1) * 100
    
        if excessCeo != 0 {
            prec, _ := big.NewFloat(excessCeo).Int64()
            excess := big.NewInt(0).Quo(gasprice, big.NewInt(prec))
            gasprice.Add(gasprice, excess)
        }
    
        tx := types.NewTransaction(nonce, contract, big.NewInt(0), gasLimit, gasprice, input)
        cost := tx.Cost()
        balance, _ := c.nmap[local].C.BalanceAt(context.TODO(), fromAccDef.Address, nil)
        if balance.Cmp(cost) < 0 {
            return nil, errors.ERR_NOT_ENOUGH_COIN
        }
        return signature.NewEthTx(nonce, fromAccDef.Address, contract, big.NewInt(0), gasLimit, gasprice, input, local), nil
    }
    //签名
    func (tx *EthTx) Sign(prvKeys []string) error {
        prvkey, err := tx.stringToEthPrvKey(prvKeys[0])
        if err != nil {
            return err
        }
        signTx, err := types.SignTx(tx.T, types.HomesteadSigner{}, prvkey)
        if err != nil {
            return err
        }
        tx.T = signTx
        tx.Signed = true
        return nil
    }
    

    boxvault项目wallet库地址,该库集成了eth,eth-erc20,btc,ltc,usdt,解决了各币种单位精度问题,实现了hd钱包功能,一个私钥多币种私钥衍生(该功能为boxvault的安全设计方可如此使用),解耦了签名功能,实现离线签名,同时可继续接入其他币种,为box团队的开源项目,其中包含了详细的文档。

    相关文章

      网友评论

        本文标题:No.3-区块链ETH之golang调用实践

        本文链接:https://www.haomeiwen.com/subject/lntkbqtx.html