AntShares 区块链的智能合约(FunctionCode)外传数据
来源:互联网 发布:数据挖掘工程师辛苦吗 编辑:程序博客网 时间:2024/05/21 09:23
上篇说到了部署智能合约,可以部署可以调用,但是现阶段官方没有提供查询FunctionCode返回值的方法,不过不要紧,AntShares是个不错的开源区块链项目,要自己加入获取FunctionCode结果值的方法不难。改开源项目不难,但是改了之后还要兼容以后的升级,那就有点麻烦,所以我这篇文章是尽量最小程度修改AntShares项目,读者愿意大改也可以。
本文修改的重点在于AntShares.dll,项目地址:https://github.com/AntShares/AntShares。本文的基本原理:智能合约的Storage.Get()执行会触发StateMachine.cs的private bool Storage_Get(ExecutionEngine engine) ,Storage.Get()会触发StateMachine.cs的private bool Storage_Put(ExecutionEngine engine) 。我的思路是,当智能合约调用Get方法时,就把Get方法的入参作为拦截对象,在AntShares.dll里面监听。所以,在写智能合约时故意使用Get变相作为智能合约往外传值(读者有兴趣的话,自己研究一下使用Put方法来拦截也可以,比Get方法修改量稍微多一点)。
智能合约调用的流程重点关注LevelDBBlockchain.cs这个源文件,其中以下代码是重点之一,我稍微改过一丢点:
case TransactionType.InvocationTransaction: { InvocationTransaction itx = (InvocationTransaction)tx; CachedScriptTable script_table = new CachedScriptTable(contracts); StateMachine service = new StateMachine(accounts, validators, assets, contracts, storages); ApplicationEngine engine = new ApplicationEngine(itx, script_table, service, itx.Gas); engine.LoadScript(itx.Script, false); if (engine.Execute() == true) { //MySocket.send("log:engine.Execute()-->true"); service.Commit(); } else { MySocket.send("log:engine.Execute()-->false"); } } break;
大概的用法是当执行调用合约时,先执行Script,再写入leveldb一些Script指定的数据,可以是系统本身所需要的数据和用户使用Put方法想要存储的数据,这顺序很重要,因为使用Get()获取刚刚Put进去的数据会出错。
接下来说说加入了哪些代码。1、在antshares新增SocketClient.cs,用于把数据通过TCP传到本机的其他软件系统,也可以用来打log,代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Net;using System.Net.Sockets;using System.Threading;namespace AntShares{ class MySocket { static SocketClient clientSocket; static public void send(String msg) { if (clientSocket == null) { clientSocket = new SocketClient(); clientSocket.connect(); } String newMsg = msg + "\r\n"; clientSocket.send(newMsg); } } class SocketClient { Socket clientSocket = null; int port = 2017; /// <summary> /// 作为客户端,只主动连接指定端口的TCP Server /// </summary> public void connect() { IPAddress ip = IPAddress.Parse("127.0.0.1"); if (clientSocket == null) clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { clientSocket.Connect(new IPEndPoint(ip, port)); } catch{} } public Boolean isConnected() { if (clientSocket != null) return clientSocket.Connected; return false; } public void send(String msg) { if (isConnected() == false) connect(); try { clientSocket.Send(Encoding.UTF8.GetBytes(msg)); } catch { } } public void close() { try { clientSocket.Shutdown(SocketShutdown.Both); //clientSocket.Close(); } catch { } } }}
PS:智能合约在VM上跑本来就是为了安全地黑盒里运行,这回突破了黑盒一点点,理应智能合约传数据到本机其他业务系统。
2、修改StateMachine.cs。智能合约调用Storage.Get()方法触发private bool Storage_Get(ExecutionEngine engine),我们只讲对private bool Storage_Get(ExecutionEngine engine)的修改,对含“result=”的Storage.Get()入参进行捕获:
private bool Storage_Get(ExecutionEngine engine) { MySocket.send("log:Storage_Get...........");//纯粹打日志 StorageContext context = (StorageContext)(byte)engine.EvaluationStack.Pop().GetBigInteger(); UInt160 script_hash = CheckStorageContext(engine, context); if (script_hash == null) return false; byte[] key = engine.EvaluationStack.Pop().GetByteArray(); StorageItem item = storages.TryGet(new StorageKey { ScriptHash = script_hash, Key = key }); engine.EvaluationStack.Push(item?.Value ?? new byte[0]); string key1 = System.Text.Encoding.UTF8.GetString(key); if (key1.IndexOf("result=") == 0)//判断是否FunctionCode函数的返回值,对"result="监视 { key1 = key1.Remove(0, "result=".Length); MySocket.send("FunctionCode Result--->" +key1); } return true; }
3、接下来贴出智能合约的源码,更多智能合约的代码看项目主页:
using AntShares.SmartContract.Framework;using AntShares.SmartContract.Framework.Services.AntShares;namespace AntShares.SmartContract{ public class HelloWorld : FunctionCode { public static void Main() { //修改AntShares.dll,通过监听get方法来获得FunctionCode的返回结果 string text = "result={\"jsonrpc\":\"2.0\",\"i\":1}"; Storage.Get(StorageContext.Current, text); } }}
智能合约使用“result=”作为监视标记,在private bool Storage_Get(ExecutionEngine engine)捕获到“result=”就把后面的json通过TCP发出去。通过TCP工具(作为本机外部系统角色)可以收到智能合约主动发出的数据:
- AntShares 区块链的智能合约(FunctionCode)外传数据
- AntShares 区块链搭建私有链与部署智能合约
- 区块链2.0:智能合约
- 区块链2.0:智能合约
- 区块链--智能合约详解
- 区块链学堂(2):最简单的智能合约
- 区块链搭建以及智能合约的运行
- 开源|基于区块链的智能合约快速上手
- AntShares区块链的节点部署与搭建私有链
- 区块链学习-智能合约与ICO
- 区块链智能合约部署初探
- Scry中文名首发:無域——开启基于区块链数据化经济的智能合约时代
- Scry中文名首发:無域——开启基于区块链数据化经济的智能合约时代
- 每日区块链:智能合约是否是区块链的最佳创新?
- 『区块链智能合约』从零构建Ethereum智能合约到实战开发
- 『区块链智能合约』从零构建Ethereum智能合约到实战开发
- 面向开发人员的区块链链代码深入研究:使用 Go 编写智能合约
- 区块链2.0(六):以太坊—开放的智能合约完整解决方案
- IP地址
- 使用maven构建多模块项目(一)
- 死锁
- Redis基本介绍
- jsp实现数据库连接
- AntShares 区块链的智能合约(FunctionCode)外传数据
- 程序设计实践课的感受
- C++ STL容器参考手册 (总册)
- Java中的try-catch-finally
- markdown语法
- 面试16: 反转链表
- 学习是程序员的必修课
- caffe mnist loss函数的理解
- 获取应用程序的签名,防止二次打包