Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
335abdce
Commit
335abdce
authored
Jun 13, 2017
by
Péter Szilágyi
Committed by
GitHub
Jun 13, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14581 from holiman/byte_opt
core/vm: improve opByte
parents
73227309
ac986579
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
174 additions
and
8 deletions
+174
-8
big.go
common/math/big.go
+28
-0
big_test.go
common/math/big_test.go
+98
-1
instructions.go
core/vm/instructions.go
+6
-7
instructions_test.go
core/vm/instructions_test.go
+42
-0
No files found.
common/math/big.go
View file @
335abdce
...
...
@@ -130,6 +130,34 @@ func PaddedBigBytes(bigint *big.Int, n int) []byte {
return
ret
}
// bigEndianByteAt returns the byte at position n,
// in Big-Endian encoding
// So n==0 returns the least significant byte
func
bigEndianByteAt
(
bigint
*
big
.
Int
,
n
int
)
byte
{
words
:=
bigint
.
Bits
()
// Check word-bucket the byte will reside in
i
:=
n
/
wordBytes
if
i
>=
len
(
words
)
{
return
byte
(
0
)
}
word
:=
words
[
i
]
// Offset of the byte
shift
:=
8
*
uint
(
n
%
wordBytes
)
return
byte
(
word
>>
shift
)
}
// Byte returns the byte at position n,
// with the supplied padlength in Little-Endian encoding.
// n==0 returns the MSB
// Example: bigint '5', padlength 32, n=31 => 5
func
Byte
(
bigint
*
big
.
Int
,
padlength
,
n
int
)
byte
{
if
n
>=
padlength
{
return
byte
(
0
)
}
return
bigEndianByteAt
(
bigint
,
padlength
-
1
-
n
)
}
// ReadBits encodes the absolute value of bigint as big-endian bytes. Callers must ensure
// that buf has enough space. If buf is too short the result will be incomplete.
func
ReadBits
(
bigint
*
big
.
Int
,
buf
[]
byte
)
{
...
...
common/math/big_test.go
View file @
335abdce
...
...
@@ -21,6 +21,8 @@ import (
"encoding/hex"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
)
func
TestHexOrDecimal256
(
t
*
testing
.
T
)
{
...
...
@@ -133,8 +135,44 @@ func TestPaddedBigBytes(t *testing.T) {
}
}
func
BenchmarkPaddedBigBytes
(
b
*
testing
.
B
)
{
func
BenchmarkPaddedBigBytes
LargePadding
(
b
*
testing
.
B
)
{
bigint
:=
MustParseBig256
(
"123456789123456789123456789123456789"
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
PaddedBigBytes
(
bigint
,
200
)
}
}
func
BenchmarkPaddedBigBytesSmallPadding
(
b
*
testing
.
B
)
{
bigint
:=
MustParseBig256
(
"0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC"
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
PaddedBigBytes
(
bigint
,
5
)
}
}
func
BenchmarkPaddedBigBytesSmallOnePadding
(
b
*
testing
.
B
)
{
bigint
:=
MustParseBig256
(
"0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC"
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
PaddedBigBytes
(
bigint
,
32
)
}
}
func
BenchmarkByteAtBrandNew
(
b
*
testing
.
B
)
{
bigint
:=
MustParseBig256
(
"0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC"
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
bigEndianByteAt
(
bigint
,
15
)
}
}
func
BenchmarkByteAt
(
b
*
testing
.
B
)
{
bigint
:=
MustParseBig256
(
"0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC"
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
bigEndianByteAt
(
bigint
,
15
)
}
}
func
BenchmarkByteAtOld
(
b
*
testing
.
B
)
{
bigint
:=
MustParseBig256
(
"0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC"
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
PaddedBigBytes
(
bigint
,
32
)
}
...
...
@@ -174,6 +212,65 @@ func TestU256(t *testing.T) {
}
}
func
TestBigEndianByteAt
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
x
string
y
int
exp
byte
}{
{
"00"
,
0
,
0x00
},
{
"01"
,
1
,
0x00
},
{
"00"
,
1
,
0x00
},
{
"01"
,
0
,
0x01
},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
0
,
0x30
},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
1
,
0x20
},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
31
,
0xAB
},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
32
,
0x00
},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
500
,
0x00
},
}
for
_
,
test
:=
range
tests
{
v
:=
new
(
big
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
x
))
actual
:=
bigEndianByteAt
(
v
,
test
.
y
)
if
actual
!=
test
.
exp
{
t
.
Fatalf
(
"Expected [%v] %v:th byte to be %v, was %v."
,
test
.
x
,
test
.
y
,
test
.
exp
,
actual
)
}
}
}
func
TestLittleEndianByteAt
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
x
string
y
int
exp
byte
}{
{
"00"
,
0
,
0x00
},
{
"01"
,
1
,
0x00
},
{
"00"
,
1
,
0x00
},
{
"01"
,
0
,
0x00
},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
0
,
0x00
},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
1
,
0x00
},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
31
,
0x00
},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
32
,
0x00
},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
0
,
0xAB
},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
1
,
0xCD
},
{
"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
,
0
,
0x00
},
{
"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
,
1
,
0xCD
},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
31
,
0x30
},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
30
,
0x20
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
32
,
0x0
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
31
,
0xFF
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
0xFFFF
,
0x0
},
}
for
_
,
test
:=
range
tests
{
v
:=
new
(
big
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
x
))
actual
:=
Byte
(
v
,
32
,
test
.
y
)
if
actual
!=
test
.
exp
{
t
.
Fatalf
(
"Expected [%v] %v:th byte to be %v, was %v."
,
test
.
x
,
test
.
y
,
test
.
exp
,
actual
)
}
}
}
func
TestS256
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
x
,
y
*
big
.
Int
}{
{
x
:
big
.
NewInt
(
0
),
y
:
big
.
NewInt
(
0
)},
...
...
core/vm/instructions.go
View file @
335abdce
...
...
@@ -256,15 +256,14 @@ func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
}
func
opByte
(
pc
*
uint64
,
evm
*
EVM
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
th
,
val
:=
stack
.
pop
(),
stack
.
p
op
()
if
th
.
Cmp
(
big
.
NewInt
(
32
)
)
<
0
{
b
yte
:=
evm
.
interpreter
.
intPool
.
get
()
.
SetInt64
(
int64
(
math
.
PaddedBigBytes
(
val
,
32
)[
th
.
Int64
()]
))
stack
.
push
(
byte
)
th
,
val
:=
stack
.
pop
(),
stack
.
p
eek
()
if
th
.
Cmp
(
common
.
Big32
)
<
0
{
b
:=
math
.
Byte
(
val
,
32
,
int
(
th
.
Int64
()
))
val
.
SetUint64
(
uint64
(
b
)
)
}
else
{
stack
.
push
(
new
(
big
.
Int
)
)
val
.
SetUint64
(
0
)
}
evm
.
interpreter
.
intPool
.
put
(
th
,
val
)
evm
.
interpreter
.
intPool
.
put
(
th
)
return
nil
,
nil
}
func
opAddmod
(
pc
*
uint64
,
evm
*
EVM
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
...
...
core/vm/instructions_test.go
0 → 100644
View file @
335abdce
package
vm
import
(
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
func
TestByteOp
(
t
*
testing
.
T
)
{
var
(
env
=
NewEVM
(
Context
{},
nil
,
params
.
TestChainConfig
,
Config
{
EnableJit
:
false
,
ForceJit
:
false
})
stack
=
newstack
()
)
tests
:=
[]
struct
{
v
string
th
uint64
expected
*
big
.
Int
}{
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
0
,
big
.
NewInt
(
0xAB
)},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
1
,
big
.
NewInt
(
0xCD
)},
{
"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
,
0
,
big
.
NewInt
(
0x00
)},
{
"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
,
1
,
big
.
NewInt
(
0xCD
)},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
31
,
big
.
NewInt
(
0x30
)},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
30
,
big
.
NewInt
(
0x20
)},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
32
,
big
.
NewInt
(
0x0
)},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
0xFFFFFFFFFFFFFFFF
,
big
.
NewInt
(
0x0
)},
}
pc
:=
uint64
(
0
)
for
_
,
test
:=
range
tests
{
val
:=
new
(
big
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
v
))
th
:=
new
(
big
.
Int
)
.
SetUint64
(
test
.
th
)
stack
.
push
(
val
)
stack
.
push
(
th
)
opByte
(
&
pc
,
env
,
nil
,
nil
,
stack
)
actual
:=
stack
.
pop
()
if
actual
.
Cmp
(
test
.
expected
)
!=
0
{
t
.
Fatalf
(
"Expected [%v] %v:th byte to be %v, was %v."
,
test
.
v
,
test
.
th
,
test
.
expected
,
actual
)
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment