From 2668b5963124594afcf7ef8f0115adaef34cb7f1 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 17 Apr 2015 16:05:36 -0700 Subject: [PATCH 1/2] =?UTF-8?q?=E2=94=AC=E2=94=80=E2=94=AC=20=EF=B8=B5=20/?= =?UTF-8?q?(.=E2=96=A1.=20\=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vm/common.go | 26 ++++ vm/vm.go | 339 ++++++++++++++++++++++++++++----------------------- 2 files changed, 211 insertions(+), 154 deletions(-) create mode 100644 vm/common.go diff --git a/vm/common.go b/vm/common.go new file mode 100644 index 000000000..00ab93c77 --- /dev/null +++ b/vm/common.go @@ -0,0 +1,26 @@ +package vm + +import ( + "math/big" +) + +// To256 +// +// "cast" the big int to a 256 big int (i.e., limit to) +var tt256 = new(big.Int).Lsh(big.NewInt(1), 256) +var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1)) +var tt255 = new(big.Int).Lsh(big.NewInt(1), 255) + +func U256(x *big.Int) *big.Int { + x.And(x, tt256m1) + return x +} + +func S256(x *big.Int) *big.Int { + if x.Cmp(tt255) < 0 { + return x + } else { + // We don't want to modify x, ever + return new(big.Int).Sub(x, tt256) + } +} diff --git a/vm/vm.go b/vm/vm.go index ba16d846a..0363a5faf 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -1,6 +1,7 @@ package vm import ( + "bytes" "errors" "fmt" "math/big" @@ -131,196 +132,252 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga return nil, nil case ADD: // 0x01 - //x, y := stack.Pop64(), stack.Pop64() - //stack.Push64(x + y) x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(flip(x[:])) - yb := new(big.Int).SetBytes(flip(y[:])) + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) sum := new(big.Int).Add(xb, yb) - stack.Push(RightPadWord256(flip(sum.Bytes()))) - dbg.Printf(" %v + %v = %v\n", xb, yb, sum) + res := LeftPadWord256(U256(sum).Bytes()) + stack.Push(res) + dbg.Printf(" %v + %v = %v (%X)\n", xb, yb, sum, res) case MUL: // 0x02 - //x, y := stack.Pop64(), stack.Pop64() - //stack.Push64(x * y) x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(flip(x[:])) - yb := new(big.Int).SetBytes(flip(y[:])) + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) prod := new(big.Int).Mul(xb, yb) - stack.Push(RightPadWord256(flip(prod.Bytes()))) - dbg.Printf(" %v * %v = %v\n", xb, yb, prod) + res := LeftPadWord256(U256(prod).Bytes()) + stack.Push(res) + dbg.Printf(" %v * %v = %v (%X)\n", xb, yb, prod, res) case SUB: // 0x03 - //x, y := stack.Pop64(), stack.Pop64() - //stack.Push64(x - y) x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(flip(x[:])) - yb := new(big.Int).SetBytes(flip(y[:])) + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) diff := new(big.Int).Sub(xb, yb) - stack.Push(RightPadWord256(flip(diff.Bytes()))) - dbg.Printf(" %v - %v = %v\n", xb, yb, diff) + res := LeftPadWord256(U256(diff).Bytes()) + stack.Push(res) + dbg.Printf(" %v - %v = %v (%X)\n", xb, yb, diff, res) case DIV: // 0x04 - //x, y := stack.Pop64(), stack.Pop64() - //stack.Push64(x / y) x, y := stack.Pop(), stack.Pop() - if y.IsZero() { // TODO + if y.IsZero() { stack.Push(Zero256) - dbg.Printf(" %x / %x = %v (TODO)\n", x, y, 0) + dbg.Printf(" %x / %x = %v\n", x, y, 0) } else { - xb := new(big.Int).SetBytes(flip(x[:])) - yb := new(big.Int).SetBytes(flip(y[:])) + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) div := new(big.Int).Div(xb, yb) - stack.Push(RightPadWord256(flip(div.Bytes()))) - dbg.Printf(" %v / %v = %v\n", xb, yb, div) + res := LeftPadWord256(U256(div).Bytes()) + stack.Push(res) + dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res) } case SDIV: // 0x05 - // TODO ... big? - x, y := int64(stack.Pop64()), int64(stack.Pop64()) - if y == 0 { // TODO + x, y := stack.Pop(), stack.Pop() + if y.IsZero() { stack.Push(Zero256) - dbg.Printf(" %v / %v = %v (TODO)\n", x, y, 0) + dbg.Printf(" %x / %x = %v\n", x, y, 0) } else { - stack.Push64(uint64(x / y)) - dbg.Printf(" %v / %v = %v\n", x, y, x/y) + xb := S256(new(big.Int).SetBytes(x[:])) + yb := S256(new(big.Int).SetBytes(y[:])) + div := new(big.Int).Div(xb, yb) + res := LeftPadWord256(U256(div).Bytes()) + stack.Push(res) + dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res) } case MOD: // 0x06 - //x, y := stack.Pop64(), stack.Pop64() x, y := stack.Pop(), stack.Pop() - if y.IsZero() { // TODO + if y.IsZero() { stack.Push(Zero256) - dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0) + dbg.Printf(" %v %% %v = %v\n", x, y, 0) } else { - xb := new(big.Int).SetBytes(flip(x[:])) - yb := new(big.Int).SetBytes(flip(y[:])) + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) mod := new(big.Int).Mod(xb, yb) - stack.Push(RightPadWord256(flip(mod.Bytes()))) - dbg.Printf(" %v %% %v = %v\n", xb, yb, mod) + res := LeftPadWord256(U256(mod).Bytes()) + stack.Push(res) + dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res) } case SMOD: // 0x07 - // TODO ... big? - x, y := int64(stack.Pop64()), int64(stack.Pop64()) - if y == 0 { // TODO + x, y := stack.Pop(), stack.Pop() + if y.IsZero() { stack.Push(Zero256) - dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0) + dbg.Printf(" %v %% %v = %v\n", x, y, 0) } else { - stack.Push64(uint64(x % y)) - dbg.Printf(" %v %% %v = %v\n", x, y, x%y) + xb := S256(new(big.Int).SetBytes(x[:])) + yb := S256(new(big.Int).SetBytes(y[:])) + mod := new(big.Int).Mod(xb, yb) + res := LeftPadWord256(U256(mod).Bytes()) + stack.Push(res) + dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res) } case ADDMOD: // 0x08 - // TODO ... big? - x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64() - if z == 0 { // TODO + x, y, z := stack.Pop(), stack.Pop(), stack.Pop() + if z.IsZero() { stack.Push(Zero256) - dbg.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0) + dbg.Printf(" %v %% %v = %v\n", x, y, 0) } else { - stack.Push64((x + y) % z) - dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x+y)%z) + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) + zb := new(big.Int).SetBytes(z[:]) + add := new(big.Int).Add(xb, yb) + mod := new(big.Int).Mod(add, zb) + res := LeftPadWord256(U256(mod).Bytes()) + stack.Push(res) + dbg.Printf(" %v + %v %% %v = %v (%X)\n", + xb, yb, zb, mod, res) } case MULMOD: // 0x09 - // TODO ... big? - x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64() - if z == 0 { // TODO + x, y, z := stack.Pop(), stack.Pop(), stack.Pop() + if z.IsZero() { stack.Push(Zero256) - dbg.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0) + dbg.Printf(" %v %% %v = %v\n", x, y, 0) } else { - stack.Push64((x * y) % z) - dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x*y)%z) + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) + zb := new(big.Int).SetBytes(z[:]) + mul := new(big.Int).Mul(xb, yb) + mod := new(big.Int).Mod(mul, zb) + res := LeftPadWord256(U256(mod).Bytes()) + stack.Push(res) + dbg.Printf(" %v * %v %% %v = %v (%X)\n", + xb, yb, zb, mod, res) } case EXP: // 0x0A - //x, y := stack.Pop64(), stack.Pop64() - //stack.Push64(ExpUint64(x, y)) x, y := stack.Pop(), stack.Pop() - xb := new(big.Int).SetBytes(flip(x[:])) - yb := new(big.Int).SetBytes(flip(y[:])) + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) pow := new(big.Int).Exp(xb, yb, big.NewInt(0)) - stack.Push(RightPadWord256(flip(pow.Bytes()))) - dbg.Printf(" %v ** %v = %v\n", xb, yb, pow) + res := LeftPadWord256(U256(pow).Bytes()) + dbg.Printf(" %v ** %v = %v (%X)\n", xb, yb, pow, res) case SIGNEXTEND: // 0x0B - x, y := stack.Pop64(), stack.Pop64() - res := (y << uint(x)) >> x - stack.Push64(res) - dbg.Printf(" (%v << %v) >> %v = %v\n", y, x, x, res) + back := stack.Pop() + backb := new(big.Int).SetBytes(back[:]) + if backb.Cmp(big.NewInt(31)) < 0 { + bit := uint(backb.Uint64()*8 + 7) + num := stack.Pop() + numb := new(big.Int).SetBytes(num[:]) + mask := new(big.Int).Lsh(big.NewInt(1), bit) + mask.Sub(mask, big.NewInt(1)) + if numb.Bit(int(bit)) == 1 { + numb.Or(numb, mask.Not(mask)) + } else { + numb.Add(numb, mask) + } + res := LeftPadWord256(U256(numb).Bytes()) + dbg.Printf(" = %v (%X)", numb, res) + stack.Push(res) + } case LT: // 0x10 - x, y := stack.Pop64(), stack.Pop64() - if x < y { + x, y := stack.Pop(), stack.Pop() + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) + if xb.Cmp(yb) < 0 { stack.Push64(1) + dbg.Printf(" %v < %v = %v\n", xb, yb, 1) } else { stack.Push(Zero256) + dbg.Printf(" %v < %v = %v\n", xb, yb, 0) } - dbg.Printf(" %v < %v = %v\n", x, y, x < y) case GT: // 0x11 - x, y := stack.Pop64(), stack.Pop64() - if x > y { + x, y := stack.Pop(), stack.Pop() + xb := new(big.Int).SetBytes(x[:]) + yb := new(big.Int).SetBytes(y[:]) + if xb.Cmp(yb) > 0 { stack.Push64(1) + dbg.Printf(" %v > %v = %v\n", xb, yb, 1) } else { stack.Push(Zero256) + dbg.Printf(" %v > %v = %v\n", xb, yb, 0) } - dbg.Printf(" %v > %v = %v\n", x, y, x > y) case SLT: // 0x12 - x, y := int64(stack.Pop64()), int64(stack.Pop64()) - if x < y { + x, y := stack.Pop(), stack.Pop() + xb := S256(new(big.Int).SetBytes(x[:])) + yb := S256(new(big.Int).SetBytes(y[:])) + if xb.Cmp(yb) < 0 { stack.Push64(1) + dbg.Printf(" %v < %v = %v\n", xb, yb, 1) } else { stack.Push(Zero256) + dbg.Printf(" %v < %v = %v\n", xb, yb, 0) } - dbg.Printf(" %v < %v = %v\n", x, y, x < y) case SGT: // 0x13 - x, y := int64(stack.Pop64()), int64(stack.Pop64()) - if x > y { + x, y := stack.Pop(), stack.Pop() + xb := S256(new(big.Int).SetBytes(x[:])) + yb := S256(new(big.Int).SetBytes(y[:])) + if xb.Cmp(yb) > 0 { stack.Push64(1) + dbg.Printf(" %v > %v = %v\n", xb, yb, 1) } else { stack.Push(Zero256) + dbg.Printf(" %v > %v = %v\n", xb, yb, 0) } - dbg.Printf(" %v > %v = %v\n", x, y, x > y) case EQ: // 0x14 - x, y := stack.Pop64(), stack.Pop64() - if x == y { + x, y := stack.Pop(), stack.Pop() + if bytes.Equal(x[:], y[:]) { stack.Push64(1) + dbg.Printf(" %X == %X = %v\n", x, y, 1) } else { stack.Push(Zero256) + dbg.Printf(" %X == %X = %v\n", x, y, 0) } - dbg.Printf(" %v == %v = %v\n", x, y, x == y) case ISZERO: // 0x15 - x := stack.Pop64() - if x == 0 { + x := stack.Pop() + if x.IsZero() { stack.Push64(1) + dbg.Printf(" %v == 0 = %v\n", x, 1) } else { stack.Push(Zero256) + dbg.Printf(" %v == 0 = %v\n", x, 0) } - dbg.Printf(" %v == 0 = %v\n", x, x == 0) case AND: // 0x16 - x, y := stack.Pop64(), stack.Pop64() - stack.Push64(x & y) - dbg.Printf(" %v & %v = %v\n", x, y, x&y) + x, y := stack.Pop(), stack.Pop() + z := [32]byte{} + for i := 0; i < 32; i++ { + z[i] = x[i] & y[i] + } + stack.Push(z) + dbg.Printf(" %X & %X = %X\n", x, y, z) + case OR: // 0x17 - x, y := stack.Pop64(), stack.Pop64() - stack.Push64(x | y) - dbg.Printf(" %v | %v = %v\n", x, y, x|y) + x, y := stack.Pop(), stack.Pop() + z := [32]byte{} + for i := 0; i < 32; i++ { + z[i] = x[i] | y[i] + } + stack.Push(z) + dbg.Printf(" %X | %X = %X\n", x, y, z) case XOR: // 0x18 - x, y := stack.Pop64(), stack.Pop64() - stack.Push64(x ^ y) - dbg.Printf(" %v ^ %v = %v\n", x, y, x^y) + x, y := stack.Pop(), stack.Pop() + z := [32]byte{} + for i := 0; i < 32; i++ { + z[i] = x[i] ^ y[i] + } + stack.Push(z) + dbg.Printf(" %X ^ %X = %X\n", x, y, z) case NOT: // 0x19 - x := stack.Pop64() - stack.Push64(^x) - dbg.Printf(" !%v = %v\n", x, ^x) + x := stack.Pop() + z := [32]byte{} + for i := 0; i < 32; i++ { + z[i] = ^x[i] + } + stack.Push(z) + dbg.Printf(" !%X = %X\n", x, z) case BYTE: // 0x1A idx, val := stack.Pop64(), stack.Pop() @@ -336,12 +393,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga return nil, firstErr(err, ErrInsufficientGas) } offset, size := stack.Pop64(), stack.Pop64() - data, ok := subslice(memory, offset, size, false) + data, ok := subslice(memory, offset, size) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } data = sha3.Sha3(data) - stack.PushBytes(flip(data)) + stack.PushBytes(data) dbg.Printf(" => (%v) %X\n", size, data) case ADDRESS: // 0x30 @@ -353,7 +410,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga if ok = useGas(gas, GasGetAccount); !ok { return nil, firstErr(err, ErrInsufficientGas) } - acc := vm.appState.GetAccount(flipWord(addr)) // TODO ensure that 20byte lengths are supported. + acc := vm.appState.GetAccount(addr) if acc == nil { return nil, firstErr(err, ErrUnknownAddress) } @@ -375,12 +432,13 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case CALLDATALOAD: // 0x35 offset := stack.Pop64() - data, ok := subslice(input, offset, 32, true) + data, ok := subslice(input, offset, 32) if !ok { return nil, firstErr(err, ErrInputOutOfBounds) } - stack.Push(RightPadWord256(data)) - dbg.Printf(" => 0x%X\n", RightPadWord256(data)) + res := LeftPadWord256(data) + stack.Push(res) + dbg.Printf(" => 0x%X\n", res) case CALLDATASIZE: // 0x36 stack.Push64(uint64(len(input))) @@ -390,11 +448,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga memOff := stack.Pop64() inputOff := stack.Pop64() length := stack.Pop64() - data, ok := subslice(input, inputOff, length, false) + data, ok := subslice(input, inputOff, length) if !ok { return nil, firstErr(err, ErrInputOutOfBounds) } - dest, ok := subslice(memory, memOff, length, false) + dest, ok := subslice(memory, memOff, length) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -410,11 +468,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga memOff := stack.Pop64() codeOff := stack.Pop64() length := stack.Pop64() - data, ok := subslice(code, codeOff, length, false) + data, ok := subslice(code, codeOff, length) if !ok { return nil, firstErr(err, ErrCodeOutOfBounds) } - dest, ok := subslice(memory, memOff, length, false) + dest, ok := subslice(memory, memOff, length) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -430,7 +488,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga if ok = useGas(gas, GasGetAccount); !ok { return nil, firstErr(err, ErrInsufficientGas) } - acc := vm.appState.GetAccount(flipWord(addr)) + acc := vm.appState.GetAccount(addr) if acc == nil { return nil, firstErr(err, ErrUnknownAddress) } @@ -444,7 +502,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga if ok = useGas(gas, GasGetAccount); !ok { return nil, firstErr(err, ErrInsufficientGas) } - acc := vm.appState.GetAccount(flipWord(addr)) + acc := vm.appState.GetAccount(addr) if acc == nil { return nil, firstErr(err, ErrUnknownAddress) } @@ -452,11 +510,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga memOff := stack.Pop64() codeOff := stack.Pop64() length := stack.Pop64() - data, ok := subslice(code, codeOff, length, false) + data, ok := subslice(code, codeOff, length) if !ok { return nil, firstErr(err, ErrCodeOutOfBounds) } - dest, ok := subslice(memory, memOff, length, false) + dest, ok := subslice(memory, memOff, length) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -491,20 +549,20 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case MLOAD: // 0x51 offset := stack.Pop64() - data, ok := subslice(memory, offset, 32, true) + data, ok := subslice(memory, offset, 32) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } - stack.Push(RightPadWord256(data)) + stack.Push(LeftPadWord256(data)) dbg.Printf(" => 0x%X\n", data) case MSTORE: // 0x52 offset, data := stack.Pop64(), stack.Pop() - dest, ok := subslice(memory, offset, 32, false) + dest, ok := subslice(memory, offset, 32) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } - copy(dest, flip(data[:])) + copy(dest, data[:]) dbg.Printf(" => 0x%X\n", data) case MSTORE8: // 0x53 @@ -532,8 +590,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga continue case JUMPI: // 0x57 - pos, cond := stack.Pop64(), stack.Pop64() - if cond >= 1 { + pos, cond := stack.Pop64(), stack.Pop() + if !cond.IsZero() { err = jump(code, pos, &pc) continue } @@ -555,11 +613,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32: a := uint64(op - PUSH1 + 1) - codeSegment, ok := subslice(code, pc+1, a, true) + codeSegment, ok := subslice(code, pc+1, a) if !ok { return nil, firstErr(err, ErrCodeOutOfBounds) } - res := RightPadWord256(codeSegment) + res := LeftPadWord256(codeSegment) stack.Push(res) pc += a dbg.Printf(" => 0x%X\n", res) @@ -581,7 +639,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga for i := 0; i < n; i++ { topics[i] = stack.Pop() } - data, ok := subslice(memory, offset, size, false) + data, ok := subslice(memory, offset, size) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -597,7 +655,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case CREATE: // 0xF0 contractValue := stack.Pop64() offset, size := stack.Pop64(), stack.Pop64() - input, ok := subslice(memory, offset, size, false) + input, ok := subslice(memory, offset, size) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -627,7 +685,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga dbg.Printf(" => %X\n", addr) // Get the arguments from the memory - args, ok := subslice(memory, inOffset, inSize, false) + args, ok := subslice(memory, inOffset, inSize) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -651,7 +709,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga if ok = useGas(gas, GasGetAccount); !ok { return nil, firstErr(err, ErrInsufficientGas) } - acc := vm.appState.GetAccount(flipWord(addr)) + acc := vm.appState.GetAccount(addr) if acc == nil { return nil, firstErr(err, ErrUnknownAddress) } @@ -667,7 +725,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga stack.Push(Zero256) } else { stack.Push(One256) - dest, ok := subslice(memory, retOffset, retSize, false) + dest, ok := subslice(memory, retOffset, retSize) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -681,7 +739,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga case RETURN: // 0xF3 offset, size := stack.Pop64(), stack.Pop64() - ret, ok := subslice(memory, offset, size, false) + ret, ok := subslice(memory, offset, size) if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } @@ -694,7 +752,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga return nil, firstErr(err, ErrInsufficientGas) } // TODO if the receiver is , then make it the fee. - receiver := vm.appState.GetAccount(flipWord(addr)) + receiver := vm.appState.GetAccount(addr) if receiver == nil { return nil, firstErr(err, ErrUnknownAddress) } @@ -715,7 +773,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga } } -func subslice(data []byte, offset, length uint64, flip_ bool) (ret []byte, ok bool) { +func subslice(data []byte, offset, length uint64) (ret []byte, ok bool) { size := uint64(len(data)) if size < offset { return nil, false @@ -726,9 +784,6 @@ func subslice(data []byte, offset, length uint64, flip_ bool) (ret []byte, ok bo ret, ok = data[offset:offset+length], true } - if flip_ { - ret = flip(ret) - } return } @@ -777,27 +832,3 @@ func transfer(from, to *Account, amount uint64) error { return nil } } - -func flip(in []byte) []byte { - l2 := len(in) / 2 - flipped := make([]byte, len(in)) - // copy the middle bit (if its even it will get overwritten) - if len(in) != 0 { - flipped[l2] = in[l2] - } - for i := 0; i < l2; i++ { - flipped[i] = in[len(in)-1-i] - flipped[len(in)-1-i] = in[i] - } - return flipped -} - -func flipWord(in Word256) Word256 { - word := Word256{} - // copy the middle bit (if its even it will get overwritten) - for i := 0; i < 16; i++ { - word[i] = in[len(in)-1-i] - word[len(in)-1-i] = in[i] - } - return word -} From b11ca1bbfc3f157bda20c12fcfd6316e76a92701 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 17 Apr 2015 17:39:50 -0700 Subject: [PATCH 2/2] =?UTF-8?q?(=E2=95=AF=C2=B0=E2=96=A1=C2=B0=EF=BC=89?= =?UTF-8?q?=E2=95=AF=EF=B8=B5=20=E2=94=BB=E2=94=81=E2=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/word.go | 10 ++++++++-- rpc/core/accounts.go | 2 +- rpc/core/txs.go | 9 ++++----- rpc/test/helpers_test.go | 2 +- rpc/test/tests_test.go | 4 ++-- state/block_cache.go | 2 +- state/execution.go | 2 +- state/tx_cache.go | 2 +- vm/native.go | 4 ++-- vm/stack.go | 5 +++-- vm/test/fake_app_state.go | 2 +- vm/test/vm_test.go | 4 ++-- 12 files changed, 27 insertions(+), 21 deletions(-) diff --git a/common/word.go b/common/word.go index 7c5c8a81a..1b62f0640 100644 --- a/common/word.go +++ b/common/word.go @@ -31,7 +31,10 @@ func (w Word256) Compare(other Word256) int { func Uint64ToWord256(i uint64) Word256 { word := Word256{} - PutUint64(word[:], i) + buf := [8]byte{} + PutUint64(buf[:], i) + word[24], word[25], word[26], word[27] = buf[7], buf[6], buf[5], buf[4] + word[28], word[29], word[30], word[31] = buf[3], buf[2], buf[1], buf[0] return word } @@ -46,7 +49,10 @@ func LeftPadWord256(bz []byte) (word Word256) { } func Uint64FromWord256(word Word256) uint64 { - return binary.LittleEndian.Uint64(word[:]) + buf := [8]byte{} + buf[0], buf[1], buf[2], buf[3] = word[31], word[30], word[29], word[28] + buf[4], buf[5], buf[6], buf[7] = word[27], word[26], word[25], word[24] + return binary.LittleEndian.Uint64(buf[:]) } //------------------------------------- diff --git a/rpc/core/accounts.go b/rpc/core/accounts.go index b6206fd9e..ba43673a0 100644 --- a/rpc/core/accounts.go +++ b/rpc/core/accounts.go @@ -36,7 +36,7 @@ func GetStorage(address, key []byte) (*ctypes.ResponseGetStorage, error) { storageRoot := account.StorageRoot storageTree := state.LoadStorage(storageRoot) - _, value := storageTree.Get(RightPadWord256(key).Bytes()) + _, value := storageTree.Get(LeftPadWord256(key).Bytes()) if value == nil { return &ctypes.ResponseGetStorage{key, nil}, nil } diff --git a/rpc/core/txs.go b/rpc/core/txs.go index 628bc6584..82ff13ef4 100644 --- a/rpc/core/txs.go +++ b/rpc/core/txs.go @@ -12,11 +12,11 @@ import ( func toVMAccount(acc *account.Account) *vm.Account { return &vm.Account{ - Address: RightPadWord256(acc.Address), + Address: LeftPadWord256(acc.Address), Balance: acc.Balance, Code: acc.Code, // This is crazy. Nonce: uint64(acc.Sequence), - StorageRoot: RightPadWord256(acc.StorageRoot), + StorageRoot: LeftPadWord256(acc.StorageRoot), Other: acc.PubKey, } } @@ -26,7 +26,6 @@ func toVMAccount(acc *account.Account) *vm.Account { // Run a contract's code on an isolated and unpersisted state // Cannot be used to create new contracts func Call(address, data []byte) (*ctypes.ResponseCall, error) { - st := consensusState.GetState() // performs a copy cache := mempoolReactor.Mempool.GetCache() outAcc := cache.GetAccount(address) @@ -38,7 +37,7 @@ func Call(address, data []byte) (*ctypes.ResponseCall, error) { txCache := state.NewTxCache(cache) params := vm.Params{ BlockHeight: uint64(st.LastBlockHeight), - BlockHash: RightPadWord256(st.LastBlockHash), + BlockHash: LeftPadWord256(st.LastBlockHash), BlockTime: st.LastBlockTime.Unix(), GasLimit: 10000000, } @@ -63,7 +62,7 @@ func CallCode(code, data []byte) (*ctypes.ResponseCall, error) { txCache := state.NewTxCache(cache) params := vm.Params{ BlockHeight: uint64(st.LastBlockHeight), - BlockHash: RightPadWord256(st.LastBlockHash), + BlockHash: LeftPadWord256(st.LastBlockHash), BlockTime: st.LastBlockTime.Unix(), GasLimit: 10000000, } diff --git a/rpc/test/helpers_test.go b/rpc/test/helpers_test.go index 7755277cc..07f05a6f2 100644 --- a/rpc/test/helpers_test.go +++ b/rpc/test/helpers_test.go @@ -288,7 +288,7 @@ func simpleContract() ([]byte, []byte, []byte) { // the is the code we need to return the contractCode when the contract is initialized lenCode := len(contractCode) // push code to the stack - //code := append([]byte{byte(0x60 + lenCode - 1)}, LeftPadWord256(contractCode).Bytes()...) + //code := append([]byte{byte(0x60 + lenCode - 1)}, RightPadWord256(contractCode).Bytes()...) code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...) // store it in memory code = append(code, []byte{0x60, 0x0, 0x52}...) diff --git a/rpc/test/tests_test.go b/rpc/test/tests_test.go index f95a42d4b..311505d0e 100644 --- a/rpc/test/tests_test.go +++ b/rpc/test/tests_test.go @@ -119,8 +119,8 @@ func testGetStorage(t *testing.T, typ string) { mempoolCount = 0 v := getStorage(t, typ, contractAddr, []byte{0x1}) - got := RightPadWord256(v) - expected := RightPadWord256([]byte{0x5}) + got := LeftPadWord256(v) + expected := LeftPadWord256([]byte{0x5}) if got.Compare(expected) != 0 { t.Fatalf("Wrong storage value. Got %x, expected %x", got.Bytes(), expected.Bytes()) } diff --git a/state/block_cache.go b/state/block_cache.go index 277754541..2eda83fa9 100644 --- a/state/block_cache.go +++ b/state/block_cache.go @@ -106,7 +106,7 @@ func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) { _, val_ := storage.Get(key.Bytes()) value = Zero256 if val_ != nil { - value = RightPadWord256(val_.([]byte)) + value = LeftPadWord256(val_.([]byte)) } cache.storages[Tuple256{addr, key}] = storageInfo{value, false} return value diff --git a/state/execution.go b/state/execution.go index 5152b16f8..cf2843dbf 100644 --- a/state/execution.go +++ b/state/execution.go @@ -395,7 +395,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea txCache = NewTxCache(blockCache) params = vm.Params{ BlockHeight: uint64(_s.LastBlockHeight), - BlockHash: RightPadWord256(_s.LastBlockHash), + BlockHash: LeftPadWord256(_s.LastBlockHash), BlockTime: _s.LastBlockTime.Unix(), GasLimit: 10000000, } diff --git a/state/tx_cache.go b/state/tx_cache.go index d5a23d6c2..d181e0472 100644 --- a/state/tx_cache.go +++ b/state/tx_cache.go @@ -158,7 +158,7 @@ func toVMAccount(acc *ac.Account) *vm.Account { Balance: acc.Balance, Code: acc.Code, // This is crazy. Nonce: uint64(acc.Sequence), - StorageRoot: RightPadWord256(acc.StorageRoot), + StorageRoot: LeftPadWord256(acc.StorageRoot), Other: acc.PubKey, } } diff --git a/vm/native.go b/vm/native.go index ad9f3f3ae..07621b92d 100644 --- a/vm/native.go +++ b/vm/native.go @@ -39,7 +39,7 @@ func ecrecoverFunc(input []byte, gas *uint64) (output []byte, err error) { return nil, err } hashed := sha3.Sha3(recovered[1:]) - return RightPadBytes(hashed, 32), nil + return LeftPadBytes(hashed, 32), nil } func sha256Func(input []byte, gas *uint64) (output []byte, err error) { @@ -73,7 +73,7 @@ func ripemd160Func(input []byte, gas *uint64) (output []byte, err error) { if err != nil { panic(err) } - return RightPadBytes(hasher.Sum(nil), 32), nil + return LeftPadBytes(hasher.Sum(nil), 32), nil } func identityFunc(input []byte, gas *uint64) (output []byte, err error) { diff --git a/vm/stack.go b/vm/stack.go index 41d50c702..17938d2c5 100644 --- a/vm/stack.go +++ b/vm/stack.go @@ -51,7 +51,7 @@ func (st *Stack) PushBytes(bz []byte) { if len(bz) != 32 { panic("Invalid bytes size: expected 32") } - st.Push(RightPadWord256(bz)) + st.Push(LeftPadWord256(bz)) } func (st *Stack) Push64(i uint64) { @@ -73,7 +73,8 @@ func (st *Stack) PopBytes() []byte { } func (st *Stack) Pop64() uint64 { - return GetUint64(st.Pop().Bytes()) + d := st.Pop() + return Uint64FromWord256(d) } func (st *Stack) Len() int { diff --git a/vm/test/fake_app_state.go b/vm/test/fake_app_state.go index 3d6f5ca22..456e3b3c9 100644 --- a/vm/test/fake_app_state.go +++ b/vm/test/fake_app_state.go @@ -90,5 +90,5 @@ func createAddress(creator *Account) Word256 { temp := make([]byte, 32+8) copy(temp, creator.Address[:]) PutUint64(temp[32:], nonce) - return RightPadWord256(sha3.Sha3(temp)[:20]) + return LeftPadWord256(sha3.Sha3(temp)[:20]) } diff --git a/vm/test/vm_test.go b/vm/test/vm_test.go index 740d0063a..ef9d88343 100644 --- a/vm/test/vm_test.go +++ b/vm/test/vm_test.go @@ -64,10 +64,10 @@ func TestSubcurrency(t *testing.T) { st := newAppState() // Create accounts account1 := &Account{ - Address: RightPadWord256(makeBytes(20)), + Address: LeftPadWord256(makeBytes(20)), } account2 := &Account{ - Address: RightPadWord256(makeBytes(20)), + Address: LeftPadWord256(makeBytes(20)), } st.accounts[account1.Address.String()] = account1 st.accounts[account2.Address.String()] = account2