微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何检索NodeJS VM状态的字节码? JavaScript 智能合约实验 ** 更新 **

如何解决如何检索NodeJS VM状态的字节码? JavaScript 智能合约实验 ** 更新 **

我正在尝试使用 NodeJS 和 VM 重现以太坊的智能合约流程。

我已经解决了一些问题,但它也提出了一个新问题。

我的目标是检索我在 NodeJS VM 实例中加载和执行的字节码;

初始状态是我在 VM 中作为字节码加载的智能合约代码

我还打了两个字节码调用。并执行。

如何从该 VM 实例中检索字节码中的新状态?

const vm = require('vm');
const v8 = require('v8');

v8.setFlagsFromString('--no-lazy');

if (Number.parseInt(process.versions.node.split('.')[0],10) >= 12) {
    v8.setFlagsFromString('--no-flush-bytecode'); // Thanks to A-Parser (@a-parser)
  }
  
  /**
 * Generates v8 bytecode buffer.
 * Could be the compile for smart contract to compile the bytecode
 * the bytecode will go on the blockchain so it can never change.
 * The input Could be a file with all the JavaScript
 * @param   {string} javascriptCode JavaScript source that will represent a smart contract on the blockchain
 * @returns {Buffer} The generated bytecode.
 */
const compileCode = function (javascriptCode) {

    if (typeof javascriptCode !== 'string') {
      throw new Error(`javascriptCode must be string. ${typeof javascriptCode} was given.`)
    }
  
    let script =  new vm.Script(javascriptCode)
    let bytecodeBuffer = script.createCachedData()

  return bytecodeBuffer;
}

/**
 * Runs v8 bytecode buffer and returns the result.
 * @param   {Buffer} bytecodeBuffer The buffer object that was created using compileCode function.
 * @returns {any}    The result of the very last statement executed in the script.
 */
const runBytecode = function (bytecodeBuffer) {

    if (!Buffer.isBuffer(bytecodeBuffer)) {
      throw new Error(`bytecodeBuffer must be a buffer object.`);
    }
  
   // fixBytecode(bytecodeBuffer);
  
    let length = readSourceHash(bytecodeBuffer);
  
    let dummyCode = "";
  
    if (length > 1) {
      dummyCode = '"' + "\u200b".repeat(length - 2) + '"'; // "\u200b" Zero width space
    }
  
    let script = new vm.Script(dummyCode,{
      cachedData: bytecodeBuffer
    });
  
    if (script.cachedDataRejected) {
      throw new Error('Invalid or incompatible cached data (cachedDataRejected)');
    }
   //console.log(bytecodeBuffer)
    return script.runInThisContext();
  };



// Todo: rewrite this function
const readSourceHash = function (bytecodeBuffer) {

    if (!Buffer.isBuffer(bytecodeBuffer)) {
      throw new Error(`bytecodeBuffer must be a buffer object.`)
    }
 
      return bytecodeBuffer.slice(8,12).reduce((sum,number,power) => sum += number * Math.pow(256,power),0)
    
  }





 /* 
  This is an example of a smart contract in javascript.
  It would get stored on the blockchain as bytecode.
  It Could be compiled from a file to.
*/




 let smartContract = ` 

                function setName(_name){ 
                    name = _name
                    console.log('name set') 
                }
                
                function getName(){
                    console.log(name)
                }
                
                `

 // we compile the smart contract into bytecode
 // the contract will be loaded in the VM
 let bytecode = compileCode(smartContract)
 runBytecode(bytecode)

 /* 
  this call will set the name in the Contract that reside in the VM
  The name is set but not wrtien anywhere yet. It is only set on this
  instance fo the VM. This change the state an we would need to recompile
  the contract with the new data and update the blockchain.
  */
 let call = "setName('Satoshi')"
 let callBytecode = compileCode(call)
 runBytecode(callBytecode)



/*
  Execute the call in the contract in the VM
  the function is just printing out the value that we pass to our javascript contract
  the state of the contract did not change 

*/

let rCall = "getName()"
let rcallBytecode = compileCode(rCall)

  runBytecode(rcallBytecode)
 //console.log(bytecode)

如何检索已加载到 VM 中的字节码并将其保存为保留在那里的名称。想象一个名称数组,每次有人加载并调用函数时,它都会向其中添加名称。然后使用该额外名称保存新的字节码。保存并传递给下一个想要运行它的虚拟机。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。