AntShares 区块链的智能合约(FunctionCode)外传数据

原创 2017年06月18日 16:43:09

上篇说到了部署智能合约,可以部署可以调用,但是现阶段官方没有提供查询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工具(作为本机外部系统角色)可以收到智能合约主动发出的数据:




版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hellogv/article/details/73432568

AntShares区块链的节点部署与搭建私有链

最近陆续体验常见的区块链开源项目,例如小蚁OnChain出的AntShares。AntShares跟其他开源区块链项目不一样,他们家是使用C#开发,基于.NET Core运行在Linux,期待未来出G...
  • hellogv
  • hellogv
  • 2017年05月15日 15:46
  • 5957

两万字深度长文!从原理到趋势,解剖风口上的区块链技术

前言:区块链不是一项新技术,而是一个新的技术组合。其关键技术包括P2P动态组网、基于密码学的共享账本、共识机制、智能合约等技术;科技史上大部分创新都是与生产力有关的,提升效率,让人做更少工作,让机器做...
  • p23onzq
  • p23onzq
  • 2018年02月21日 00:00
  • 184

区块链-智能合约简单脚本编写方法(solidity)

“一个智能合约是一套以数字形式定义的承诺(promises) ,包括合约参与方可以在上面执行这些承诺的协议。”协议是技术实现(technical implementation),在这个基础上,合约承诺...
  • AAA123524457
  • AAA123524457
  • 2016年10月17日 10:28
  • 1659

区块链-4:区块链的基本类型和智能合约

一、公有链 公有链是指全世界任何人都可读取、任何人都能发送交易且交易能获得有效确认,任何 人都能参与共识过程的区块链 有如下几个特点: 保护用户免受开发者的影响 在公有链中程序开发者无权干...
  • mlyjqx
  • mlyjqx
  • 2018年02月28日 10:15
  • 262

区块链和智能合约的关系

尽管比特币(Bitcoin)和以太坊(Ethereum)是经常被一起提及的两个词,但实际上,比特币与以太坊有着很大的区别。它们唯一的共同点是,以太坊也是一个在区块链之上运行的加密资产。与比特币仅仅是一...
  • jiankeufo
  • jiankeufo
  • 2018年01月18日 10:18
  • 927

区块链学习日记———智能合约部署

区块链学习———智能合约的部署 记录自己学习以及过程中所遇到的问题
  • qindong564950620
  • qindong564950620
  • 2017年03月16日 22:23
  • 662

区块链开发(三)编写调试第一个以太坊智能合约

一、       智能合约IDE简介     目前以太坊上支持三种语言编写智能合约,     Solidity:类似JavaScript,这是以太坊官方推荐语言,也是最流行的智能合约语言。具体用法...
  • ziyuzhiye
  • ziyuzhiye
  • 2017年01月05日 18:25
  • 1601

区块链--智能合约详解

区块链学习--智能合约详解 1、账户 2、以太币和gas 3、合约交易-合约账户 4、传统合约与智能合约的区别 参考:bitcoin-on-nodejs...
  • petermsh
  • petermsh
  • 2017年10月28日 19:34
  • 995

区块链2.0(三):智能合约应用案列及相关法律问题

区块链中的合约或者说智能合约意味着区块链交易远不止买卖比特币这些简单的交易,将会有广泛的指令嵌入到区块链中。 传统合约是双方或者多方共同协议做或不做某事来换取某些东西,前提是互相要信任彼此会履行...
  • u014345860
  • u014345860
  • 2017年08月26日 09:40
  • 405

区块链学堂(2):最简单的智能合约

最简单的智能合约 最简单的一个智能合约 pragma solidity 0.4.9; contract DemoTypes { function f(uint a) returns (uin...
  • ethchinese
  • ethchinese
  • 2017年02月27日 14:45
  • 3655
收藏助手
不良信息举报
您举报文章:AntShares 区块链的智能合约(FunctionCode)外传数据
举报原因:
原因补充:

(最多只允许输入30个字)