美文网首页
智能合约入门2——library部署及调用

智能合约入门2——library部署及调用

作者: prophet__ | 来源:发表于2020-10-13 22:05 被阅读0次

    我们不造轮子,我们只是轮子的搬运工。

    我们在进行软件开发的时候,往往会用到别人写的一些现成的东西,像python里的tensorflow、numpy、pandas,C++里的Qt、 boost等等。这类别人写好的代码往往被称作“库”(也叫轮子),引用别人的库需要有现成的库文件。

    在区块链上,同样也包含这种概念,但是与我们一般编译程序不同,我们引用的代码是已经部署在区块链网络里的代码,不需要本地有这个库。

    这一步的教程比较复杂,分为5个部分:
    1.自己撰写一个Libirary。
    2.生成调用Library所需的Metadata。
    3.编辑Metadata。
    4.链接Library并部署。
    5.查看部署详情。

    撰写Library

    library其实跟普通的contract没什么区别,只不过它是以library作为key word并且可以让其他的contract调用已经部署过的library,这样不用重复造轮子。

    pragma solidity >=0.4.22 <0.6.0;
    
    contract test {
        function get () public returns(uint) {
            // should call a library method which returns `3`
            return LibraryForTest.getFromLib();    
        }
    }
    
    library LibraryForTest {
        function getFromLib() public returns(uint) {
            return 3;
        }
    }
    

    首先是在library里制作一个getFromLib的函数,返回值为3,然后再在contract当中建立一个get函数,调用这个getFromLib函数。

    要注意的是,在solidity语言当中,返回值的类型也要卸载函数定义当中,通过returns定义返回值类型,这里使用的是uint也就是无符号整型。

    进行编译和部署,在部署完后可以在界面内进行调用。(建议使用Ropsten测试网,可以领取测试的手续费)

    生成调用Library所需的Metadata

    在之前的程序当中,我们将contract和library写在同一个文件里,但是实际上在部署之后,他们将会是两个不同的地址,那么如果contract想引用这个library,就必须知道它的地址。

    但library的地址并不会直接显示在合约当中,在编译好的contract的bytecode当中,会有一个placeholder指向这个library的address。

    所以在部署一个调用library的contract之前,你需要生成这个contract的metadata,然后将要调用的library的address加入到metadata当中。

    接下来我们就来看一下如何找metadata。

    metadata在编译(compile)的时候产生,当我们选择左下角的设定,打勾generate metadata的选项,再进行编译。就可以在文件里找到sampleContract_metadata.json的文件。

    编辑Metadata

    Metadata的deploy当中有我们在编译过程中所需library的所有address。

        "deploy": {
            "VM:-": {
                "linkReferences": {
                    "browser/.learneth/Deploy with Libraries/2_Generate_Metadata/2_contractSimpleLibrary.sol": {
                        "aLib": "<address>"
                    }
                },
                "autoDeployLib": true
            },
            "main:1": {
                "linkReferences": {
                    "browser/.learneth/Deploy with Libraries/2_Generate_Metadata/2_contractSimpleLibrary.sol": {
                        "aLib": "<address>"
                    }
                },
                "autoDeployLib": true
            },
    

    关键词<address>包含的是已经部署过的library的address,对于每个网络需要进行具体说明。

    autoDeployLib是一个bool量,代表remix在进行部署前是否要自动部署这个lib。

    一般来说,autoDeploy是true,<address>不会被调用到,remix会进行自动部署。

    但是为了更好的模仿现实情况,我们在这里将通过手动链接已经在网络上部署过的VM Lib。

    首先,我们将VM的autoDeply设置为false。

    手动连接library并部署

    如果这个时候我们直接切换到deploy选择simplecontract进行部署,会出现如下错误:

    那么首先,我们要先进行VM的部署,在deploy界面上更改contract,有个libA,进行部署。

    部署后下面会有一个复制address的按钮,点击就可以复制已经部署好的library地址。

    然后复制粘帖到之前我们找到的那个json文件当中。

            "VM:-": {
                "linkReferences": {
                    "browser/.learneth/Deploy with Libraries/2_Generate_Metadata/2_contractSimpleLibrary.sol": {
                        "aLib": "0xf8e81D47203A594245E36C48e151709F0C19fBe8"
                    }
                },
                "autoDeployLib": false
            },
    

    再次跳回之前的deploy界面,选择simplecontract进行部署,部署即可成功。

    查看部署信息

    在编译后我们可以查看它的bytecode,在下面有一行小字可以复制到clipboard,贴出来大概是这样:

    {
        "linkReferences": {
            "browser/contractSimpleLibrary.sol": {
                "LibraryForTest": [
                    {
                        "length": 20,
                        "start": 109
                    }
                ]
            }
        },
        "object": "608060405234801561001057600080fd5b50610101806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80636d4ce63c14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b600073__$92b7644c0d8dcc07d172959bb8f25dc6be$__6387cc10e16040518163ffffffff1660e01b815260040160206040518083038186803b158015608e57600080fd5b505af415801560a1573d6000803e3d6000fd5b505050506040513d602081101560b657600080fd5b810190808051906020019092919050505090509056fea265627a7a72315820cc244a6979e5f20d4286dc7691fb21c2e6c9a88c694caea792eb02614a93ad0a64736f6c63430005110032",
        "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO ... ",
        "sourceMap": "34:107:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34:107:0;;;;;;;"
    }
    

    这个东西看起来可能有些复杂,前面的linkReference内的内容代表被调用库的信息。后面的object(bytecode)代表这个合约将被存在区块链上的字节流,也就是说整个合约能在区块链上查到的就是这一串数字。

    在bytecode当中有一段__$92b7644c0d8dcc07d172959bb8f25dc6be __代表的是指向被调用library地址的占位符(placeholder)。

    opcodes是区块链实现操作的语言,用于进行交易和转移,被脚本引擎Script所调用。sourcemap是用于调试的源码映射(这个我也不太懂什么意思)。

    结语

    对于library的部署和调用是智能合约使用当中很基础的一部分,但是从尝试当中也能发现并不是一件简单的事情。由于要将合约放到一个全世界都可以调用的地方,势必要进行压缩和删减。

    将部署和调用分开也是为了更好地使用contract和library这两个功能不同的关键字。从架构设计上来说,还有很多值得学习和研究的地方。

    参考资料:https://blog.csdn.net/weixin_40959706/article/details/90719518

    https://blog.csdn.net/HiBlock/article/details/81395375

    相关文章

      网友评论

          本文标题:智能合约入门2——library部署及调用

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