【问题标题】:Adding new custom opcode to solidity将新的自定义操作码添加到solidity
【发布时间】:2021-05-28 13:46:34
【问题描述】:

我在向solidity 添加新操作码时遇到问题。我正在使用 solc(在 C++ 上)和 geth(在 Go 上的以太坊)。我想添加新的操作码,它采用address payable, uint256, uint256, bytes memory 并返回bytes memory。所以我的返回值有问题。

下面的一些代码和平,我将跳过一些文件,以使问题更短。

  1. Solc
  • libsolidity/codegen/ExpressionCompiler.cpp
// ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::MyOpcode:
{
    acceptAndConvert(*arguments[0], *function.parameterTypes()[0], true);
    acceptAndConvert(*arguments[1], *function.parameterTypes()[1], true);
    acceptAndConvert(*arguments[2], *function.parameterTypes()[2], true);
    arguments[3]->accept(*this);
    utils().fetchFreeMemoryPointer();
    utils().packedEncode(
        {arguments[3]->annotation().type},
        {TypeProvider::array(DataLocation::Memory, true)}
    );
    utils().toSizeAfterFreeMemoryPointer();

    m_context << Instruction::MYOPCODE;
}
  • libsolidity/analysis/GlobalContext.cpp
// inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariables()
magicVarDecl("myopcode", TypeProvider::function(strings{"address payable", "uint256", "uint256", "bytes memory"}, strings{"bytes memory"}, FunctionType::Kind::MyOpcode, false, StateMutability::Payable)),
  • libevmasm/Instruction.cpp
// static std::map<Instruction, InstructionInfo> const c_instructionInfo =
{ Instruction::MYOPCODE,       { "MYOPCODE",          0, 5, 1, true, Tier::Base } }
  1. 格思
  • core/vm/jump_table.go
// func newFrontierInstructionSet() JumpTable {
CALLACTOR: {
    execute:    opMyOpCode,
    dynamicGas: gasCallActor,
    minStack:   minStack(5, 1),
    maxStack:   maxStack(5, 1),
    memorySize: memoryReturn,
    writes:     true,
    returns:    true,
},
  • core/vm/instructions.go
func opMyOpcode(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
    inoffset, insize := callContext.stack.pop(), callContext.stack.pop()
    params := callContext.memory.GetPtr(int64(inoffset.Uint64()), int64(insize.Uint64()))

    secondValue := callContext.stack.pop()

    firstValue := callContext.stack.pop()

    addr := callContext.stack.pop()

    // ... Do smth with input ...

    outoffset := inoffset.Uint64() + insize.Uint64()

    callContext.memory.Set(outoffset, 1, []byte{0x2})
    tmp := make([]byte, 1)
    tmp[0] = 0x98
    callContext.memory.Set(outoffset + 1, 1, tmp)

    callContext.stack.push(uint256.NewInt().SetUint64(outoffset))

    return tmp, nil
}
  1. 智能合约
pragma solidity >=0.6.0; // SPDX-License-Identifier: GPL-3
contract test {
    event ReturnValue(address payable _from, bytes data);
    function f() public returns(bytes memory){
        address payable addr1 = payable(msg.sender);
        bytes memory params = new bytes(2);
        params[0] = 0x21;
        params[1] = 0x22;
        bytes memory result = myopcode(addr1, 0x11, 0x12, params);
        emit ReturnValue(addr1, result);
        return result;
    }
}

当我运行该代码时,我得到invalid jump destination。那么,我需要做什么才能让我的代码正常工作?

【问题讨论】:

  • 可能没有人知道回答你的问题,因为它是如此的小众,全世界只有少数人想过它。最好直接向 Geth 开发人员询问。

标签: ethereum solidity opcode


【解决方案1】:

我找到了一个解决方案,它确实看起来很愚蠢,但是开发人员已经提供了这个案例。你只需要utils().returnDataToArray()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多