币币合约执行解析(包含部分源码)

比原项目仓库:

Github地址:https://github.com/Bytom/bytom

Gitee地址:https://gitee.com/BytomBlockchain/bytom

本文解析的为比原提供的币币合约 模板如下:

contract TradeOffer(assetRequested: Asset,
                    amountRequested: Amount,
                    seller: Program,
                    cancelKey: PublicKey) locks offered {
  clause trade() requires payment: amountRequested of assetRequested {
    lock payment with seller
    unlock offered
  }
  clause cancel(sellerSig: Signature) {
    verify checkTxSig(cancelKey, sellerSig)
    unlock offered
  }
}

导读: 初次接触比原只能合约的请点击比原智能合约入门Equity 语言入门 学习,方便更好的理解该文档

锁定合约

第一步:调用create-account-receiver 生成 control_program

以下是相关代码片段:

sendHttpPost("{\"account_id\":\"0IJVD7MNG0A02\"}","create-account-receiver","http://127.0.0.1:9888","");

第二步调用list-pubkeys 获取 pubkey

以下是相关代码片段:

sendHttpPost("{\"account_id\":\"0IJVD7MNG0A02\"}","list-pubkeys","http://127.0.0.1:9888","");

第三步: 将1 2步获取的值调用compile接口编译合约获得program 合约程序

以下是相关代码片段:

            JSONObject param=new JSONObject();
            JSONArray agrs=new JSONArray();
            //合约的四个参数值
            JSONObject assetParam=new JSONObject();
            assetParam.put("string","81d097312645696daea84b761d2898d950d8fba0de06c9267d8513b16663dd3a");
            agrs.put(assetParam);
            JSONObject amountParam=new JSONObject();
            amountParam.put("integer",200000000l);
            agrs.put(amountParam);
            JSONObject programParam=new JSONObject();
            programParam.put("string",control_program);
            agrs.put(programParam);
            JSONObject publicKeyParam=new JSONObject();
            publicKeyParam.put("string",pubkey);
            agrs.put(publicKeyParam);
            param.put("agrs",agrs);
            param.put("contract","contract TradeOffer(assetRequested: Asset, amountRequested: Amount, seller: Program, cancelKey: PublicKey) locks offered { clause trade() requires payment: amountRequested of assetRequested { lock payment with seller unlock offered } clause cancel(sellerSig: Signature) { verify checkTxSig(cancelKey, sellerSig) unlock offered } }");
            //调用编译合约
            sendHttpPost(param.toString(),"list-pubkeys","http://127.0.0.1:9888","");

第四步:将program 传入build-transaction接口去build一个交易的到data

以下是相关代码片段:

            param=new JSONObject();
            agrs=new JSONArray();
            JSONObject spendAccount=new JSONObject();
            spendAccount.put("account_id","0H757LPD00A02");
            spendAccount.put("amount",9909099090000l);
            spendAccount.put("asset_id","161b9767b664df907fa926a31f9e835236e57f3e9ccc5f80c12bd97723322652");
            spendAccount.put("type","spend_account");
            agrs.put(spendAccount);
            JSONObject controlAccount=new JSONObject();
            controlAccount.put("control_program",program);
            controlAccount.put("amount",9909099090000l);
            controlAccount.put("asset_id","161b9767b664df907fa926a31f9e835236e57f3e9ccc5f80c12bd97723322652");
            controlAccount.put("type","control_program");
            agrs.put(controlAccount);
            JSONObject spendAccount2=new JSONObject();
            spendAccount2.put("account_id","0H757LPD00A02");
            spendAccount2.put("amount",6000000l);
            spendAccount2.put("asset_id","ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
            spendAccount2.put("type","spend_account");
            agrs.put(spendAccount2);
            param.put("actions",agrs);
            param.put("ttl",0);
            sendHttpPost(param.toString(),"build-transaction","http://127.0.0.1:9888","");

第五步:输入密码调用sign-transaction签名第四步build的data 得到raw_transaction

以下是相关代码片段:

            param=new JSONObject();
            param.put("password","xxx");
            param.put("transaction",data);
            sendHttpPost(param.toString(),"sign-transaction","http://127.0.0.1:9888","");

第六步:调用submit-transactions提交交易

以下是相关代码片段:

            param=new JSONObject();
            param.put("raw_transaction",raw_transaction);
            sendHttpPost(param.toString(),"submit-transactions","http://127.0.0.1:9888","");

解锁/取消合约

首先需要decode出生成合约时候的参数

调用list-unspent-outputs 获取生成的合约信息获取program

以下是相关代码片段:

param=new JSONObject();
        param.put("id",outputid);
        param.put("smart_contract",true);
        sendHttpPost(param.toString(),"list-unspent-outputs","http://127.0.0.1:9888","");

调用decode-program 传入获取生成的合约参数信息

以下是相关代码片段:

param=new JSONObject();
        param.put("program",program);
        sendHttpPost(param.toString(),"decode-program","http://127.0.0.1:9888","");

需要注意的是decode出来的为值是逆序的(后续会有文章详细介绍)

解锁/取消其实就是把生成合约的步骤中的第三步去掉,替换调用生成合约第四步的参数即可

取消合约的构造参数如下:

                spendAccountUnspentOutput = arguments: [{
                  type: ‘raw_tx_signature‘,
                  // 生成合约第二步的pubkeylist 详情
                  raw_data: {
                    derivation_path: pubkeylist.pubkey_infos[0].derivation_path,
                    xpub: pubkeylist.root_xpub
                  }
                }, {
                  type: ‘data‘,
                  raw_data: {
                    // 参数偏移量 在一个合约里是固定的
                    value: ‘13000000‘
                  }
                }],
                output_id: output_id,
                type: ‘spend_account_unspent_output‘
              }
              const controlAction = {
                type: ‘control_program‘,
                amount: 100000000,
                asset_id: asset_id,
                control_program:control_program
              }
              const gasAction = {
                type: ‘spend_account‘,
                account_id:account_id,
                asset_alias: ‘BTM‘,
                amount: 50000000
              }

执行合约的参数构造如下:

           const spendAccountUnspentOutput = {
                arguments: [{
                  type: ‘data‘,
                  raw_data: {
                    // 执行合约输入资产偏移量
                    value: ‘00000000‘
                  }
                }],
                output_id: output_id,
                type: ‘spend_account_unspent_output‘
              }
              // 合约执行提供的资产
              const issueControlAction = {
                control_program: control_program,
                amount:  100000000,
                asset_id: asset_id,
                type: ‘control_program‘
              }
              // 合约执行提供的资产
              const issueSpendAction = {
                account_id: account_id,
                amount: 100000000,
                asset_id: asset_id,
                type: ‘spend_account‘
              }
              // 旷工费
              const gasAction = {
                type: ‘spend_account‘,
                account_id: account_id,
                asset_alias: ‘BTM‘,
                amount: 50000000
              }
              // 合约执行获得资产对象
              const controlAction = {
                type: ‘control_program‘,
                amount:  100000000,
                asset_id: asset_id,
                control_program: compileData.control_program
              }

build 操作其实就是指定输入输出的过程,详情请查看 官方build文档官方api文档

备注

调用比原基于okhttp接口javautil 如下:

    public static String sendHttpPost(String bodyStr,String method,String bytomApiserverUrl,String bytomApiserverToken) throws IOException {
        OkHttpClient client = new OkHttpClient();
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, bodyStr);
        Request request = new Request.Builder()
                .url(bytomApiserverUrl+"/"+method)
                .post(body)
                .addHeader("cache-control", "no-cache")
                .addHeader("Connection", "close")
                .build();
        if (bytomApiserverUrl==null || bytomApiserverUrl.contains("127.0.0.1") || bytomApiserverUrl.contains("localhost")){

        }else {
            byte[] encodedAuth = Base64.encodeBase64(bytomApiserverToken.getBytes(Charset.forName("US-ASCII")));
            String authHeader = "Basic " + new String(encodedAuth);
            request = new Request.Builder()
                    .url(bytomApiserverUrl+"/"+method)
                    .post(body)
                    .addHeader("authorization", authHeader)
                    .addHeader("cache-control", "no-cache")
                    .addHeader("Connection", "close")
                    .build();
        }
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

原文地址:https://www.cnblogs.com/bytom/p/9661433.html

时间: 2024-10-09 06:08:26

币币合约执行解析(包含部分源码)的相关文章

Spring 源码解析之HandlerAdapter源码解析(二)

Spring 源码解析之HandlerAdapter源码解析(二) 前言 看这篇之前需要有Spring 源码解析之HandlerMapping源码解析(一)这篇的基础,这篇主要是把请求流程中的调用controller流程单独拿出来了 解决上篇文章遗留的问题 getHandler(processedRequest) 这个方法是如何查找到对应处理的HandlerExecutionChain和HandlerMapping的,比如说静态资源的处理和请求的处理肯定是不同的HandlerMapping ge

转 深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)

深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇) 最近太忙了,一直没时间继续更新博客,今天忙里偷闲继续我的Mybatis学习之旅.在前九篇中,介绍了mybatis的配置以及使用, 那么本篇将走进mybatis的源码,分析mybatis 的执行流程, 好啦,鄙人不喜欢口水话,还是直接上干活吧: 1. SqlSessionFactory 与 SqlSession. 通过前面的章节对于mybatis 的介绍及使用,大家都能体会到SqlSession的重要性了吧, 没错,从表面上来看,

Tiny语言执行环境TM机源码

TM机就是TINY语言编译器编译之后的汇编代码的执行环境.TM机的主要功能是将TM的汇编代码读入和执行,它具有一般计算机类似的精简指令级RISC.TM汇编语言和一般的Intel汇编语言差点儿相同,包含寄存器寻址.操作符等,非常easy理解.一条典型的代码如:LD 0,10(1),这里面10(1)就是寄存器1中地址为基址,10为偏移地址,寻址结果放入寄存器0.三目操作符:MUL 0,1,0表示将寄存器1和寄存器2的相乘结果放入寄存器0.接下来開始一部分一部分的分析TM机的源码. TM源码例如以下:

Spring 源码解析之DispatcherServlet源码解析(五)

Spring 源码解析之DispatcherServlet源码解析(五) 前言 本文需要有前四篇文章的基础,才能够清晰易懂,有兴趣可以先看看详细的流程,这篇文章可以说是第一篇文章,也可以说是前四篇文章的的汇总,Spring的整个请求流程都是围绕着DispatcherServlet进行的 类结构图 根据类的结构来说DispatcherServlet本身也是继承了HttpServlet的,所有的请求都是根据这一个Servlet来进行转发的,同时解释了为什么需要在web.xml进行如下配置,因为Spr

【Spark Core】任务执行机制和Task源码浅析2

引言 上一小节<任务执行机制和Task源码浅析1>介绍了Executor的注册过程. 这一小节,我将从Executor端,就接收LaunchTask消息之后Executor的执行任务过程进行介绍. 1. Executor的launchTasks函数 DriverActor提交任务,发送LaunchTask指令给CoarseGrainedExecutorBackend,接收到指令之后,让它内部的executor来发起任务,即调用空闲的executor的launchTask函数. 下面是Coars

AOP执行增强-Spring 源码系列(5)

AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProcessor-Spring 源码(3) 事件机制-Spring 源码(4) AOP执行增强-Spring 源码系列(5) AOP的核心就是个动态代理,Spring进行了大量抽象和封装形成一个方便上层使用的基础模块. 而动态代理的两种实现都在上一篇中提供了代码 直接ProxyFactoryBean入手来

Spring 源码解析之ViewResolver源码解析(四)

Spring 源码解析之ViewResolver源码解析(四) 1 ViewResolver类功能解析 1.1 ViewResolver Interface to be implemented by objects that can resolve views by name. View state doesn't change during the running of the application, so implementations are free to cache views. I

JAVA常用集合源码解析系列-ArrayList源码解析(基于JDK8)

文章系作者原创,如有转载请注明出处,如有雷同,那就雷同吧~(who care!) 一.写在前面 这是源码分析计划的第一篇,博主准备把一些常用的集合源码过一遍,比如:ArrayList.HashMap及其对应的线程安全实现,此文章作为自己相关学习的一个小结,记录学习成果的同时,也希望对有缘的朋友提供些许帮助. 当然,能力所限,难免有纰漏,希望发现的朋友能够予以指出,不胜感激,以免误导了大家! 二.稳扎稳打过源码 首先,是源码内部的成员变量定义以及构造方法: 1 /** 2 * Default in

深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)

原文地址:http://www.cnblogs.com/dongying/p/4142476.html 最近太忙了,一直没时间继续更新博客,今天忙里偷闲继续我的Mybatis学习之旅.在前九篇中,介绍了mybatis的配置以及使用, 那么本篇将走进mybatis的源码,分析mybatis 的执行流程, 好啦,鄙人不喜欢口水话,还是直接上干活吧: 1. SqlSessionFactory 与 SqlSession. 通过前面的章节对于mybatis 的介绍及使用,大家都能体会到SqlSession