WICC(维基链)智能合约API Bug定位修复过程

一、关于维基链WICC

1、自行查看相关资料

(1)官方网站
(2)Github
(2)开发者中心

二、维基链提供智能合约Dapp开发

从源码可知WICC底层基于bitcoin,上层是运行Lua虚拟机,智能合约跟以太坊、EOS类似,特殊是由Lua开发

三、开发过程遇到的问题

1、由开发者接口文档可知其智能合约API是由底层mylib库提供合约与链数据的交互

2、mylib库GetTxConfirmHeight接口函数调用失败

(1)GetTxConfirmHeight接口说明

(2)由文档可知其功能是通过hash查询其上链时的区块高度

  • 以某合约交易hash值cfad02ea148ca0a763baaf67735c010023bb75c88509f6a94e87921a54182f02 为例,可在维基链测试网区块浏览器查询到结果如下图,确认高度为639083
    在这里插入图片描述

(3) 问题分析过程

  • 测试代码如下
        -- cfad02ea148ca0a763baaf67735c010023bb75c88509f6a94e87921a54182f02  --hash值
        local opened_hash_table={0xcf,0xad,0x02,0xea,0x14,0x8c,0xa0,0xa7,0x63,0xba,0xaf,0x67,0x73,0x5c,0x01,0x00,0x23,0xbb,0x75,0xc8,0x85,0x09,0xf6,0xa9,0x4e,0x87,0x92,0x1a,0x54,0x18,0x2f,0x02}
        local confirm_height = mylib.GetTxConFirmHeight(Unpack(opened_hash_table))

        print("confirm_height=",confirm_height)
  • 结果打印输出结果一直如下,即取不到hash被确认的高度
confirm_height=	nil

(4)查看底层接口代码

c++功底还不够深,看不出啥问题

static int ExGetTxConfirmHeightFunc(lua_State *L) {
    vector<std::shared_ptr < vector<unsigned char> > > retdata;

    if(!GetArray(L,retdata) ||retdata.size() != 1|| retdata.at(0).get()->size() != 32)
    {
        return RetFalse("ExGetTxConfirmHeightFunc para err1");
    }

   uint256 hash1(*retdata.at(0));
   //LogPrint("vm","ExGetTxContractsFunc1:%s",hash1.GetHex().c_str());

    CVmRunEvn* pVmRunEvn = GetVmRunEvn(L);
    if(NULL == pVmRunEvn)
    {
        return RetFalse("pVmRunEvn is NULL");
    }

    int nHeight = GetTxConfirmHeight(hash1, *pVmRunEvn->GetScriptDB());
      if(-1 == nHeight)
      {
              return RetFalse("ExGetTxConfirmHeightFunc para err2");
      }
      else{
         if(lua_checkstack(L,sizeof(lua_Number))){
                      lua_pushnumber(L,(lua_Number)nHeight);
                      return 1 ;
         }else{
                 LogPrint("vm","%s\r\n", "ExGetCurRunEnvHeightFunc stack overflow");
                 return 0;
         }
      }
}

(5)换个思路:有没有其他入参也是hash的接口调用是正常的?对比一下代码

功夫不负有心人,GetTxContracts接口也是入参为hash,写测试代码发现此接口是正常的,同样的入参,一个正常一个异常,对比一下函数实现

static int ExGetTxContractsFunc(lua_State *L) {

	vector<std::shared_ptr < vector<unsigned char> > > retdata;
    if(!GetArray(L,retdata) ||retdata.size() != 1 || retdata.at(0).get()->size() != 32)
    {
    	return RetFalse(string(__FUNCTION__)+"para  err !");
    }

    CVmRunEvn* pVmRunEvn = GetVmRunEvn(L);
    if(NULL == pVmRunEvn)
    {
    	return RetFalse("pVmRunEvn is NULL");
    }

    vector<unsigned char> vec_hash(retdata.at(0).get()->rbegin(), retdata.at(0).get()->rend());
	CDataStream tep1(vec_hash, SER_DISK, CLIENT_VERSION);
	uint256 hash1;
	tep1 >>hash1;

	std::shared_ptr<CBaseTransaction> pBaseTx;

	if (GetTransaction(pBaseTx, hash1, *pVmRunEvn->GetScriptDB(), false)) {
		CTransaction *tx = static_cast<CTransaction*>(pBaseTx.get());
		 return RetRstToLua(L, tx->vContract);
	}

	return 0;
}

(6)对比发现亮点

由以下图片可见,ExGetTxConfirmHeightFunc 函数取入参hash直接进行操作,ExGetTxContractsFunc函数对入参hash进行倒序后再操作,加打印信息调试确实两者的hash有倒序的区别
在这里插入图片描述

(7)解决方法:在操作之前对hash进行倒序

在这里插入图片描述

(8)同样的代码测试通过

confirm_height=	639083.0

注意:链上虚拟机版本问题,输出的高度值为Number类型 :123456.0,开发者使用此值的时候需要注意

3、同样的问题出现在mylib库GetBlockHash接口函数中

取到的hash值为被倒序了,解决方法同上
在这里插入图片描述

4、修改之后引入的问题

由于区块链的特性是去中心化的,WICC共识机制为DPOS,目前为11个超级节点随机轮流记账出块,本地节点通过以上修改之后合约可以正常获得数据,但是由于超级节点没有同步更新
所以如果只修改本地节点,调用修复后的接口后,区块同步会停止
原因未找到,有进展后续会更新…

发布了32 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/u010159567/article/details/85538081
今日推荐