From 7346178bf3c94b47c0fce5d9a81b8fe3b96857b9 Mon Sep 17 00:00:00 2001 From: KIMSJ Date: Fri, 22 Feb 2019 23:50:29 +0900 Subject: [PATCH] v0.1.0 --- koa_test.go | 166 ++++++++++++++-------------- opcode/constant.go | 46 +++++--- opcode/constant_test.go | 4 + translate/compiler.go | 10 +- translate/compiler_internal_test.go | 112 +++++++++++++------ vm/asm.go | 9 +- vm/vm.go | 17 ++- vm/vm_test.go | 138 +++++++++++++++-------- 8 files changed, 313 insertions(+), 189 deletions(-) diff --git a/koa_test.go b/koa_test.go index a400ee1d..98c18c55 100644 --- a/koa_test.go +++ b/koa_test.go @@ -21,6 +21,10 @@ import ( "os" "testing" + "bytes" + "encoding/hex" + + "github.com/DE-labtory/koa/abi" "github.com/DE-labtory/koa/translate" ) @@ -372,85 +376,85 @@ func TestCompile(t *testing.T) { } func TestExecute(t *testing.T) { - ///* - //contract { - // func addVariable() int { - // int a = 5 - // int b = 10 - // return a + b - // } - // - // func addNative() int { - // return 5 + 10 - // } - // - // func addArgs(a int, b int) int { - // return a + b - // } - //} - // */ - //firstContractRawBytecode, err := hex.DecodeString("21000000000000001b24302100000000652f6077141521000000000000001c29302100000000a82ed9f7141521000000000000003629302100000000bdbaf70e141521000000000000003c29322100000000000000052100000000000000082100000000000000002321000000000000000a210000000000000008210000000000000008232100000000000000082100000000000000002221000000000000000821000000000000000822012621000000000000000521000000000000000a01262100000000000000002521000000000000000821000000000000001023210000000000000001252100000000000000082100000000000000182321000000000000000821000000000000001022210000000000000008210000000000000018220126") - //if err != nil { - // t.Error(err) - //} - // - ///* - //contract { - // func hello() string{ - // return "hello!" - // } - //} - // */ - //secondContractRawBytecode, err := hex.DecodeString("21000000000000000b2430210000000019ff1d21141521000000000000000c2932212268656c6c6f212226") - //if err != nil { - // t.Error(err) - //} - // - //firstArgs1, err := abi.Encode() - //firstArgs2, err := abi.Encode() - //firstArgs3, err := abi.Encode(5, 10) - //second1, err := abi.Encode() - // - //tests := []struct { - // RawBytecode []byte - // Func []byte - // Args []byte - // output []byte - //}{ - // { - // RawBytecode: firstContractRawBytecode, - // Func: abi.Selector("addVariable()"), - // Args: firstArgs1, - // output: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f}, - // }, - // { - // RawBytecode: firstContractRawBytecode, - // Func: abi.Selector("addNative()"), - // Args: firstArgs2, - // output: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f}, - // }, - // { - // RawBytecode: firstContractRawBytecode, - // Func: abi.Selector("addArgs(int,int)"), - // Args: firstArgs3, - // output: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f}, - // }, - // { - // RawBytecode: secondContractRawBytecode, - // Func: abi.Selector("hello()"), - // Args: second1, - // output: []byte{0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0x22}, - // }, - //} - // - //for _, test := range tests { - // output, err := Execute(test.RawBytecode, test.Func, test.Args) - // if err != nil { - // t.Error(err) - // } - // - // if !bytes.Equal(test.output, output) { - // t.Errorf("Invalid output - expected=%x, got=%x ", test.output, output) - // } - //} + /* + contract { + func addVariable() int { + int a = 5 + int b = 10 + return a + b + } + + func addNative() int { + return 5 + 10 + } + + func addArgs(a int, b int) int { + return a + b + } + } + */ + firstContractRawBytecode, err := hex.DecodeString("2100000000000000202421000000000000001e25312100000000652f6077141521000000000000001f30312100000000a82ed9f7141521000000000000003930312100000000c6be6f42141521000000000000003f30332100000000000000052100000000000000082100000000000000002321000000000000000a210000000000000008210000000000000008232100000000000000082100000000000000002221000000000000000821000000000000000822012721000000000000000521000000000000000a01272100000000000000002621000000000000000821000000000000001023210000000000000001262100000000000000082100000000000000182321000000000000000821000000000000001022210000000000000008210000000000000018220127") + if err != nil { + t.Error(err) + } + + /* + contract { + func hello() string{ + return "hello!" + } + } + */ + secondContractRawBytecode, err := hex.DecodeString("2100000000000000002421000000000000000e2531210000000019ff1d21141521000000000000000f3033212268656c6c6f212227") + if err != nil { + t.Error(err) + } + + firstArgs1, err := abi.Encode() + firstArgs2, err := abi.Encode() + firstArgs3, err := abi.Encode(5, 10) + second1, err := abi.Encode() + + tests := []struct { + RawBytecode []byte + Func []byte + Args []byte + output []byte + }{ + { + RawBytecode: firstContractRawBytecode, + Func: abi.Selector("addVariable()"), + Args: firstArgs1, + output: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f}, + }, + { + RawBytecode: firstContractRawBytecode, + Func: abi.Selector("addNative()"), + Args: firstArgs2, + output: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f}, + }, + { + RawBytecode: firstContractRawBytecode, + Func: abi.Selector("addArgs(int,int)"), + Args: firstArgs3, + output: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f}, + }, + { + RawBytecode: secondContractRawBytecode, + Func: abi.Selector("hello()"), + Args: second1, + output: []byte{0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0x22}, + }, + } + + for _, test := range tests { + output, err := Execute(test.RawBytecode, test.Func, test.Args) + if err != nil { + t.Error(err) + } + + if !bytes.Equal(test.output, output) { + t.Errorf("Invalid output - expected=%x, got=%x ", test.output, output) + } + } } diff --git a/opcode/constant.go b/opcode/constant.go index 76ae3bba..6616e90d 100644 --- a/opcode/constant.go +++ b/opcode/constant.go @@ -208,6 +208,16 @@ const ( // memory[offset:offset+size] = value Mstore Type = 0x23 + // Set memory size + // + // Ex) + // + // [size] ==> + // [y] [y] + // + // memory[offset:offset+size] = value + Msize Type = 0x24 + // Get the function selector information in the CallFunc. // `Func` data is 4bytes of Keccak(function(params)) // @@ -216,7 +226,7 @@ const ( // [x] ==> [x] // [y] [y] // [x] is 4byte which encoded as function selector - LoadFunc Type = 0x24 + LoadFunc Type = 0x25 // Get the function arguments in the CallFunc. // 'Args' is arguments encoded as a bytes value according to abi. @@ -225,7 +235,7 @@ const ( // // [index] ==> [Callfunc.Args[index]] // [y] [y] - LoadArgs Type = 0x25 + LoadArgs Type = 0x26 // Jump to position at which function was called // Ex) @@ -233,20 +243,20 @@ const ( // [funcSel] // [position] ==> [value] // [y] [y] - Returning Type = 0x26 + Returning Type = 0x27 // pop the data which present specific pc to jump // The opcode pointed to by pc must be JumpDst. - Jump Type = 0x27 + Jump Type = 0x28 // jumpDst should be where the jump will be. - JumpDst Type = 0x28 + JumpDst Type = 0x29 // Pop the first two items in the stack. // First item pointed to where to jump. // Second item should be bool data that decide to jump. // If second item is false, jump to first item(pc) pointed to - Jumpi Type = 0x29 + Jumpi Type = 0x30 // Duplicate data that exists at the top of the stack. // @@ -254,7 +264,7 @@ const ( // [a] // [a] ==> [a] // [b] [b] - DUP Type = 0x30 + DUP Type = 0x31 // Swap the first two items in the stack // @@ -263,10 +273,10 @@ const ( // [a] [b] // [b] ==> [a] // [c] [c] - SWAP Type = 0x31 + SWAP Type = 0x32 // Jump to last position (Terminate the contract) - Exit Type = 0x32 + Exit Type = 0x33 ) // Change the bytecode of an opcode to string. @@ -309,22 +319,24 @@ func (p Type) String() (string, error) { case 0x23: return "Mstore", nil case 0x24: - return "LoadFunc", nil + return "Msize", nil case 0x25: - return "LoadArgs", nil + return "LoadFunc", nil case 0x26: - return "Returning", nil + return "LoadArgs", nil case 0x27: - return "Jump", nil + return "Returning", nil case 0x28: - return "JumpDst", nil + return "Jump", nil case 0x29: - return "Jumpi", nil + return "JumpDst", nil case 0x30: - return "DUP", nil + return "Jumpi", nil case 0x31: - return "SWAP", nil + return "DUP", nil case 0x32: + return "SWAP", nil + case 0x33: return "Exit", nil default: diff --git a/opcode/constant_test.go b/opcode/constant_test.go index e8c1673f..da39d55b 100644 --- a/opcode/constant_test.go +++ b/opcode/constant_test.go @@ -99,6 +99,10 @@ func TestType_String(t *testing.T) { opcode.Mstore, "Mstore", }, + { + opcode.Msize, + "Msize", + }, { opcode.LoadFunc, "LoadFunc", diff --git a/translate/compiler.go b/translate/compiler.go index 4b6068eb..3d2274bb 100644 --- a/translate/compiler.go +++ b/translate/compiler.go @@ -63,18 +63,21 @@ func CompileContract(c ast.Contract) (Asm, error) { return *asm, err } } - + println("!!! : " + asm.String()) // Compile Memory size with updated memory table. // And replace expected memory size with new memory size of the memory table. if err := compileMemSize(asm, memTracer); err != nil { return *asm, err } + println("!!! : " + asm.String()) + // Compile Function jumper with updated FuncMap. // And replace expected function jumper with new function jumper if err := compileFuncJmpr(c, asm, funcMap); err != nil { return *asm, err } + println("!!! : " + asm.String()) return *asm, nil } @@ -88,6 +91,7 @@ func createMemSizePlaceholder(asm *Asm) error { return err } asm.Emerge(opcode.Push, operand) + asm.Emerge(opcode.Msize) return nil } @@ -143,7 +147,7 @@ func compileMemSize(asm *Asm, tracer MemTracer) error { return err } - if err := asm.ReplaceOperandAt(0, operand); err != nil { + if err := asm.ReplaceOperandAt(1, operand); err != nil { return err } @@ -193,7 +197,7 @@ func fillFuncJmpr(asm *Asm, funcJmpr Asm) error { } for i, asmCode := range funcJmpr.AsmCodes { - asm.AsmCodes[i] = asmCode + asm.AsmCodes[i+3] = asmCode } return nil diff --git a/translate/compiler_internal_test.go b/translate/compiler_internal_test.go index 4962b758..aa454f6b 100644 --- a/translate/compiler_internal_test.go +++ b/translate/compiler_internal_test.go @@ -75,15 +75,15 @@ func TestCreateFuncJmprPlaceholder(t *testing.T) { }, // LoadFunc { - RawByte: []byte{0x24}, + RawByte: []byte{0x25}, Value: "LoadFunc", }, // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, - // Push c5d2460100000000 + // Push 00000000c5d24601 { RawByte: []byte{0x21}, Value: "Push", @@ -113,12 +113,12 @@ func TestCreateFuncJmprPlaceholder(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, // Exit { - RawByte: []byte{0x32}, + RawByte: []byte{0x33}, Value: "Exit", }, }, @@ -218,7 +218,7 @@ func TestCompileExit(t *testing.T) { expect: Asm{ AsmCodes: []AsmCode{ { - RawByte: []byte{0x32}, + RawByte: []byte{0x33}, Value: "Exit", }, }, @@ -265,6 +265,18 @@ func TestCompileFuncJmpr(t *testing.T) { }, asm: &Asm{ AsmCodes: []AsmCode{ + { + RawByte: []byte{0x21}, + Value: "Push", + }, + { + RawByte: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + Value: "0000000000000000", + }, + { + RawByte: []byte{0x24}, + Value: "Msize", + }, // Push 0000000000000000 { RawByte: []byte{0x21}, @@ -276,12 +288,12 @@ func TestCompileFuncJmpr(t *testing.T) { }, // LoadFunc { - RawByte: []byte{0x24}, + RawByte: []byte{0x25}, Value: "LoadFunc", }, // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, // Push c5d2460100000000 @@ -314,12 +326,12 @@ func TestCompileFuncJmpr(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, // Push c5d2460100000000 @@ -352,18 +364,30 @@ func TestCompileFuncJmpr(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, // Returning { - RawByte: []byte{0x26}, + RawByte: []byte{0x27}, Value: "Returning", }, }, }, expectAsm: &Asm{ AsmCodes: []AsmCode{ + { + RawByte: []byte{0x21}, + Value: "Push", + }, + { + RawByte: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + Value: "0000000000000000", + }, + { + RawByte: []byte{0x24}, + Value: "Msize", + }, // Push 000000000000000a { RawByte: []byte{0x21}, @@ -375,12 +399,12 @@ func TestCompileFuncJmpr(t *testing.T) { }, // LoadFunc { - RawByte: []byte{0x24}, + RawByte: []byte{0x25}, Value: "LoadFunc", }, // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, // Push 00000000c2985578 @@ -413,12 +437,12 @@ func TestCompileFuncJmpr(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, // Push 000000007edba6c8 @@ -451,12 +475,12 @@ func TestCompileFuncJmpr(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, // Exit { - RawByte: []byte{0x32}, + RawByte: []byte{0x33}, Value: "Exit", }, }, @@ -494,6 +518,18 @@ func TestFillFuncJmpr(t *testing.T) { { asm: &Asm{ AsmCodes: []AsmCode{ + { + RawByte: []byte{0x21}, + Value: "Push", + }, + { + RawByte: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + Value: "0000000000000000", + }, + { + RawByte: []byte{0x24}, + Value: "Msize", + }, // Push 0000000000000000 { RawByte: []byte{0x21}, @@ -505,12 +541,12 @@ func TestFillFuncJmpr(t *testing.T) { }, // LoadFunc { - RawByte: []byte{0x24}, + RawByte: []byte{0x25}, Value: "LoadFunc", }, // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, // Push 0000000000000000 @@ -543,12 +579,12 @@ func TestFillFuncJmpr(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, // Returning { - RawByte: []byte{0x26}, + RawByte: []byte{0x27}, Value: "Returning", }, // Push 0000000000000000 @@ -584,12 +620,12 @@ func TestFillFuncJmpr(t *testing.T) { }, // LoadFunc { - RawByte: []byte{0x24}, + RawByte: []byte{0x25}, Value: "LoadFunc", }, // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, // Push 0000000012345678 @@ -622,18 +658,30 @@ func TestFillFuncJmpr(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, // Returning { - RawByte: []byte{0x26}, + RawByte: []byte{0x27}, Value: "Returning", }, }, }, expect: &Asm{ AsmCodes: []AsmCode{ + { + RawByte: []byte{0x21}, + Value: "Push", + }, + { + RawByte: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + Value: "0000000000000000", + }, + { + RawByte: []byte{0x24}, + Value: "Msize", + }, // Push 0000000000000000 { RawByte: []byte{0x21}, @@ -645,12 +693,12 @@ func TestFillFuncJmpr(t *testing.T) { }, // LoadFunc { - RawByte: []byte{0x24}, + RawByte: []byte{0x25}, Value: "LoadFunc", }, // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, // Push 0000000012345678 @@ -683,12 +731,12 @@ func TestFillFuncJmpr(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, // Returning { - RawByte: []byte{0x26}, + RawByte: []byte{0x27}, Value: "Returning", }, // Push 0000000000000000 @@ -742,7 +790,7 @@ func TestCompileFuncSel(t *testing.T) { AsmCodes: []AsmCode{ // DUP { - RawByte: []byte{0x30}, + RawByte: []byte{0x31}, Value: "DUP", }, // Push e3170de100000000 @@ -775,7 +823,7 @@ func TestCompileFuncSel(t *testing.T) { }, // Jumpi { - RawByte: []byte{0x29}, + RawByte: []byte{0x30}, Value: "Jumpi", }, }, diff --git a/vm/asm.go b/vm/asm.go index 7d5d37d5..a2272cb6 100644 --- a/vm/asm.go +++ b/vm/asm.go @@ -43,17 +43,18 @@ var opCodes = map[opcode.Type]opCode{ opcode.Push: push{}, opcode.Mload: mload{}, opcode.Mstore: mstore{}, + opcode.Msize: msize{}, opcode.LoadFunc: loadfunc{}, opcode.LoadArgs: loadargs{}, opcode.Returning: returning{}, opcode.Jump: jump{}, opcode.JumpDst: jumpDst{}, - opcode.Jumpi: jumpi{}, // 0x30 range - opcode.DUP: dup{}, - opcode.SWAP: swap{}, - opcode.Exit: exit{}, + opcode.Jumpi: jumpi{}, + opcode.DUP: dup{}, + opcode.SWAP: swap{}, + opcode.Exit: exit{}, } // Converts rawByteCode to assembly code. diff --git a/vm/vm.go b/vm/vm.go index efa92115..2dd04171 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -126,14 +126,15 @@ type pop struct{} type push struct{} type mload struct{} type mstore struct{} +type msize struct{} type loadfunc struct{} type loadargs struct{} type returning struct{} type jump struct{} type jumpDst struct{} -type jumpi struct{} // 0x30 range +type jumpi struct{} type dup struct{} type swap struct{} type exit struct{} @@ -375,8 +376,8 @@ func (mload) hex() []uint8 { func (mstore) Do(stack *Stack, _ asmReader, memory *Memory, _ *CallFunc) error { offset, size, value := stack.Pop(), stack.Pop(), stack.Pop() - memSize := uint64(memory.Len()) + uint64(size) - memory.Resize(memSize) + //memSize := uint64(memory.Len()) + uint64(size) + //memory.Resize(memSize) convertedValue := int64ToBytes(int64(value)) memory.Sets(uint64(offset), uint64(size), convertedValue) @@ -387,6 +388,16 @@ func (mstore) hex() []uint8 { return []uint8{uint8(opcode.Mstore)} } +func (msize) Do(stack *Stack, _ asmReader, memory *Memory, _ *CallFunc) error { + size := stack.Pop() + memory.Resize(uint64(size)) + return nil +} + +func (msize) hex() []uint8 { + return []uint8{uint8(opcode.Mstore)} +} + func (loadfunc) Do(stack *Stack, _ asmReader, _ *Memory, callfunc *CallFunc) error { function := callfunc.function() diff --git a/vm/vm_test.go b/vm/vm_test.go index 02ae2ad4..7323f257 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -109,65 +109,68 @@ func TestExecute(t *testing.T) { funcSel3, err := encoding.EncodeOperand(ABI.Methods[2].ID()) testByteCode := makeTestByteCode( + uint8(opcode.Push), int64ToBytes(32), // 0 , 1 + uint8(opcode.Msize), // 2 + // Exit position - uint8(opcode.Push), int64ToBytes(27), // 0, 1 + uint8(opcode.Push), int64ToBytes(30), // 3, 4 // Function Jumper - uint8(opcode.LoadFunc), // 2 - uint8(opcode.DUP), // 3 - uint8(opcode.Push), funcSel1, // 4, 5 - uint8(opcode.EQ), // 6 - uint8(opcode.NOT), // 7 - uint8(opcode.Push), int64ToBytes(28), // 8, 9 - uint8(opcode.Jumpi), // 10 - - uint8(opcode.DUP), // 11 - uint8(opcode.Push), funcSel2, // 12, 13 - uint8(opcode.EQ), // 14 - uint8(opcode.NOT), //15 - uint8(opcode.Push), int64ToBytes(54), // 16, 17 - uint8(opcode.Jumpi), // 18 - - uint8(opcode.DUP), // 19 - uint8(opcode.Push), funcSel3, // 20, 21 - uint8(opcode.EQ), // 22 - uint8(opcode.NOT), // 23 - uint8(opcode.Push), int64ToBytes(60), // 24, 25 - uint8(opcode.Jumpi), // 26 - - uint8(opcode.Exit), // 27 + uint8(opcode.LoadFunc), // 5 + uint8(opcode.DUP), // 6 + uint8(opcode.Push), funcSel1, // 7, 8 + uint8(opcode.EQ), // 9 + uint8(opcode.NOT), // 10 + uint8(opcode.Push), int64ToBytes(31), // 11, 12 + uint8(opcode.Jumpi), // 13 + + uint8(opcode.DUP), // 14 + uint8(opcode.Push), funcSel2, // 15, 16 + uint8(opcode.EQ), // 17 + uint8(opcode.NOT), // 18 + uint8(opcode.Push), int64ToBytes(57), // 19, 20 + uint8(opcode.Jumpi), // 21 + + uint8(opcode.DUP), // 22 + uint8(opcode.Push), funcSel3, // 23, 24 + uint8(opcode.EQ), // 25 + uint8(opcode.NOT), // 26 + uint8(opcode.Push), int64ToBytes(63), // 27, 28 + uint8(opcode.Jumpi), // 29 + + uint8(opcode.Exit), // 30 // Function 'addVariable' - uint8(opcode.Push), int64ToBytes(5), // 28, 29 - uint8(opcode.Push), int64ToBytes(8), // 30, 31 - uint8(opcode.Push), int64ToBytes(0), // 32, 33 - uint8(opcode.Mstore), // 34 - uint8(opcode.Push), int64ToBytes(10), // 35, 36 - uint8(opcode.Push), int64ToBytes(8), // 37, 38 - uint8(opcode.Push), int64ToBytes(8), // 39, 40 - uint8(opcode.Mstore), // 41 + uint8(opcode.Push), int64ToBytes(5), // 31, 32 + uint8(opcode.Push), int64ToBytes(8), // 33, 34 + uint8(opcode.Push), int64ToBytes(0), // 35, 36 + uint8(opcode.Mstore), // 37 + uint8(opcode.Push), int64ToBytes(10), // 38, 39 + uint8(opcode.Push), int64ToBytes(8), // 40, 41 uint8(opcode.Push), int64ToBytes(8), // 42, 43 - uint8(opcode.Push), int64ToBytes(0), // 44, 45 - uint8(opcode.Mload), // 46 - uint8(opcode.Push), int64ToBytes(8), // 47, 48 - uint8(opcode.Push), int64ToBytes(8), // 49, 50 - uint8(opcode.Mload), // 51 - uint8(opcode.Add), // 52 - uint8(opcode.Returning), // 53 + uint8(opcode.Mstore), // 44 + uint8(opcode.Push), int64ToBytes(8), // 45, 46 + uint8(opcode.Push), int64ToBytes(0), // 47, 48 + uint8(opcode.Mload), // 49 + uint8(opcode.Push), int64ToBytes(8), // 50, 51 + uint8(opcode.Push), int64ToBytes(8), // 52, 53 + uint8(opcode.Mload), // 54 + uint8(opcode.Add), // 55 + uint8(opcode.Returning), // 56 // Function 'addNative' - uint8(opcode.Push), int64ToBytes(5), // 54, 55 - uint8(opcode.Push), int64ToBytes(10), // 56, 57 - uint8(opcode.Add), // 58 - uint8(opcode.Returning), // 59 + uint8(opcode.Push), int64ToBytes(5), // 57, 58 + uint8(opcode.Push), int64ToBytes(10), // 59, 60 + uint8(opcode.Add), // 61 + uint8(opcode.Returning), // 62 // Function 'addArgs' - uint8(opcode.Push), int64ToBytes(0), // 60, 61 - uint8(opcode.LoadArgs), // 62 - uint8(opcode.Push), int64ToBytes(1), // 63, 64 - uint8(opcode.LoadArgs), // 65 - uint8(opcode.Add), // 66 - uint8(opcode.Returning), // 67 + uint8(opcode.Push), int64ToBytes(0), // 63, 64 + uint8(opcode.LoadArgs), // 65 + uint8(opcode.Push), int64ToBytes(1), // 66, 67 + uint8(opcode.LoadArgs), // 68 + uint8(opcode.Add), // 69 + uint8(opcode.Returning), // 70 ) encodedParams, err := abi.Encode(5, 10) @@ -732,6 +735,8 @@ func TestMload(t *testing.T) { func TestMstore(t *testing.T) { testByteCode := makeTestByteCode( + uint8(opcode.Push), int64ToBytes(16), + uint8(opcode.Msize), uint8(opcode.Push), int64ToBytes(20), // value uint8(opcode.Push), int64ToBytes(8), // size uint8(opcode.Push), int64ToBytes(0), // offset @@ -778,6 +783,41 @@ func TestMstore(t *testing.T) { } } +func TestMsize(t *testing.T) { + testByteCode := makeTestByteCode( + uint8(opcode.Push), int64ToBytes(20), // size + uint8(opcode.Msize), + ) + + testExpected := []struct { + size uint64 + result uint64 + }{ + { + size: 20, + result: 20, + }, + } + + memory := NewMemory() + + stack, err := Execute(testByteCode, memory, nil) + if err != nil { + t.Error(err) + } + + if stack.Len() != 0 { + t.Errorf("Invalid stack size - expected=%d, got =%d", 0, stack.Len()) + } + + for _, test := range testExpected { + size := memory.Len() + if uint64(size) != test.result { + t.Errorf("Invalid memory size - expected=%x, got=%x", test.result, size) + } + } +} + func TestLoadFunc(t *testing.T) { testByteCode := makeTestByteCode( uint8(opcode.LoadFunc),