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

Mad*_*ams 5 javascript virtual-machine node.js smartcontracts

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

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

我的目标是在 NodeJS 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)
Run Code Online (Sandbox Code Playgroud)

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