如何检索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 (将#修改为@)