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
f8d8b56b
Unverified
Commit
f8d8b56b
authored
Aug 14, 2017
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/vm: optimize copy-less data retrievals
parent
d8aaa3a2
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
75 additions
and
54 deletions
+75
-54
common.go
core/vm/common.go
+15
-1
contracts.go
core/vm/contracts.go
+55
-48
contracts_test.go
core/vm/contracts_test.go
+1
-1
instructions.go
core/vm/instructions.go
+4
-4
No files found.
core/vm/common.go
View file @
f8d8b56b
...
...
@@ -34,7 +34,21 @@ func calcMemSize(off, l *big.Int) *big.Int {
// getData returns a slice from the data based on the start and size and pads
// up to size with zero's. This function is overflow safe.
func
getData
(
data
[]
byte
,
start
,
size
*
big
.
Int
)
[]
byte
{
func
getData
(
data
[]
byte
,
start
uint64
,
size
uint64
)
[]
byte
{
length
:=
uint64
(
len
(
data
))
if
start
>
length
{
start
=
length
}
end
:=
start
+
size
if
end
>
length
{
end
=
length
}
return
common
.
RightPadBytes
(
data
[
start
:
end
],
int
(
size
))
}
// getDataBig returns a slice from the data based on the start and size and pads
// up to size with zero's. This function is overflow safe.
func
getDataBig
(
data
[]
byte
,
start
*
big
.
Int
,
size
*
big
.
Int
)
[]
byte
{
dlen
:=
big
.
NewInt
(
int64
(
len
(
data
)))
s
:=
math
.
BigMin
(
start
,
dlen
)
...
...
core/vm/contracts.go
View file @
f8d8b56b
...
...
@@ -149,30 +149,41 @@ func (c *dataCopy) Run(in []byte) ([]byte, error) {
// bigModExp implements a native big integer exponential modular operation.
type
bigModExp
struct
{}
var
(
big1
=
big
.
NewInt
(
1
)
big4
=
big
.
NewInt
(
4
)
big8
=
big
.
NewInt
(
8
)
big16
=
big
.
NewInt
(
16
)
big32
=
big
.
NewInt
(
32
)
big64
=
big
.
NewInt
(
64
)
big96
=
big
.
NewInt
(
96
)
big480
=
big
.
NewInt
(
480
)
big1024
=
big
.
NewInt
(
1024
)
big3072
=
big
.
NewInt
(
3072
)
big199680
=
big
.
NewInt
(
199680
)
)
// RequiredGas returns the gas required to execute the pre-compiled contract.
func
(
c
*
bigModExp
)
RequiredGas
(
input
[]
byte
)
uint64
{
// Pad the input with zeroes to the minimum size to read the field lengths
input
=
common
.
RightPadBytes
(
input
,
96
)
var
(
baseLen
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
:
32
]
)
expLen
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
32
:
64
]
)
modLen
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
64
:
96
]
)
baseLen
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
0
,
32
)
)
expLen
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
32
,
32
)
)
modLen
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
64
,
32
)
)
)
input
=
input
[
96
:
]
if
len
(
input
)
>
96
{
input
=
input
[
96
:
]
}
else
{
input
=
input
[
:
0
]
}
// Retrieve the head 32 bytes of exp for the adjusted exponent length
var
expHead
*
big
.
Int
if
big
.
NewInt
(
int64
(
len
(
input
)))
.
Cmp
(
baseLen
)
<=
0
{
expHead
=
new
(
big
.
Int
)
}
else
{
offset
:=
int
(
baseLen
.
Uint64
())
input
=
common
.
RightPadBytes
(
input
,
offset
+
32
)
if
expLen
.
Cmp
(
big
.
NewInt
(
32
))
>
0
{
expHead
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
offset
:
offset
+
32
])
if
expLen
.
Cmp
(
big32
)
>
0
{
expHead
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
baseLen
.
Uint64
(),
32
))
}
else
{
expHead
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
offset
:
offset
+
int
(
expLen
.
Uint64
())]
)
expHead
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
baseLen
.
Uint64
(),
expLen
.
Uint64
())
)
}
}
// Calculate the adjusted exponent length
...
...
@@ -181,29 +192,29 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
msb
=
bitlen
-
1
}
adjExpLen
:=
new
(
big
.
Int
)
if
expLen
.
Cmp
(
big
.
NewInt
(
32
)
)
>
0
{
adjExpLen
.
Sub
(
expLen
,
big
.
NewInt
(
32
)
)
adjExpLen
.
Mul
(
big
.
NewInt
(
8
)
,
adjExpLen
)
if
expLen
.
Cmp
(
big
32
)
>
0
{
adjExpLen
.
Sub
(
expLen
,
big
32
)
adjExpLen
.
Mul
(
big
8
,
adjExpLen
)
}
adjExpLen
.
Add
(
adjExpLen
,
big
.
NewInt
(
int64
(
msb
)))
// Calculate the gas cost of the operation
gas
:=
new
(
big
.
Int
)
.
Set
(
math
.
BigMax
(
modLen
,
baseLen
))
switch
{
case
gas
.
Cmp
(
big
.
NewInt
(
64
)
)
<=
0
:
case
gas
.
Cmp
(
big
64
)
<=
0
:
gas
.
Mul
(
gas
,
gas
)
case
gas
.
Cmp
(
big
.
NewInt
(
1024
)
)
<=
0
:
case
gas
.
Cmp
(
big
1024
)
<=
0
:
gas
=
new
(
big
.
Int
)
.
Add
(
new
(
big
.
Int
)
.
Div
(
new
(
big
.
Int
)
.
Mul
(
gas
,
gas
),
big
.
NewInt
(
4
)
),
new
(
big
.
Int
)
.
Sub
(
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
96
),
gas
),
big
.
NewInt
(
3072
)
),
new
(
big
.
Int
)
.
Div
(
new
(
big
.
Int
)
.
Mul
(
gas
,
gas
),
big
4
),
new
(
big
.
Int
)
.
Sub
(
new
(
big
.
Int
)
.
Mul
(
big
96
,
gas
),
big3072
),
)
default
:
gas
=
new
(
big
.
Int
)
.
Add
(
new
(
big
.
Int
)
.
Div
(
new
(
big
.
Int
)
.
Mul
(
gas
,
gas
),
big
.
NewInt
(
16
)
),
new
(
big
.
Int
)
.
Sub
(
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
480
),
gas
),
big
.
NewInt
(
199680
)
),
new
(
big
.
Int
)
.
Div
(
new
(
big
.
Int
)
.
Mul
(
gas
,
gas
),
big
16
),
new
(
big
.
Int
)
.
Sub
(
new
(
big
.
Int
)
.
Mul
(
big
480
,
gas
),
big199680
),
)
}
gas
.
Mul
(
gas
,
math
.
BigMax
(
adjExpLen
,
big
.
NewInt
(
1
)
))
gas
.
Mul
(
gas
,
math
.
BigMax
(
adjExpLen
,
big
1
))
gas
.
Div
(
gas
,
new
(
big
.
Int
)
.
SetUint64
(
params
.
ModExpQuadCoeffDiv
))
if
gas
.
BitLen
()
>
64
{
...
...
@@ -213,23 +224,25 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
}
func
(
c
*
bigModExp
)
Run
(
input
[]
byte
)
([]
byte
,
error
)
{
// Pad the input with zeroes to the minimum size to read the field lengths
input
=
common
.
RightPadBytes
(
input
,
96
)
var
(
baseLen
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
:
32
]
)
.
Uint64
()
expLen
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
32
:
64
]
)
.
Uint64
()
modLen
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
64
:
96
]
)
.
Uint64
()
baseLen
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
0
,
32
)
)
.
Uint64
()
expLen
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
32
,
32
)
)
.
Uint64
()
modLen
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
64
,
32
)
)
.
Uint64
()
)
input
=
input
[
96
:
]
// Pad the input with zeroes to the minimum size to read the field contents
input
=
common
.
RightPadBytes
(
input
,
int
(
baseLen
+
expLen
+
modLen
))
if
len
(
input
)
>
96
{
input
=
input
[
96
:
]
}
else
{
input
=
input
[
:
0
]
}
// Handle a special case when both the base and mod length is zero
if
baseLen
==
0
&&
modLen
==
0
{
return
[]
byte
{},
nil
}
// Retrieve the operands and execute the exponentiation
var
(
base
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
:
baseLen
]
)
exp
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
baseLen
:
baseLen
+
expLen
]
)
mod
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
baseLen
+
expLen
:
baseLen
+
expLen
+
modLen
]
)
base
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
0
,
baseLen
)
)
exp
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
baseLen
,
expLen
)
)
mod
=
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
baseLen
+
expLen
,
modLen
)
)
)
if
mod
.
BitLen
()
==
0
{
// Modulo 0 is undefined, return zero
...
...
@@ -286,14 +299,11 @@ func (c *bn256Add) RequiredGas(input []byte) uint64 {
}
func
(
c
*
bn256Add
)
Run
(
input
[]
byte
)
([]
byte
,
error
)
{
// Ensure we have enough data to operate on
input
=
common
.
RightPadBytes
(
input
,
128
)
x
,
err
:=
newCurvePoint
(
input
[
:
64
])
x
,
err
:=
newCurvePoint
(
getData
(
input
,
0
,
64
))
if
err
!=
nil
{
return
nil
,
err
}
y
,
err
:=
newCurvePoint
(
input
[
64
:
128
]
)
y
,
err
:=
newCurvePoint
(
getData
(
input
,
64
,
64
)
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -310,14 +320,11 @@ func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 {
}
func
(
c
*
bn256ScalarMul
)
Run
(
input
[]
byte
)
([]
byte
,
error
)
{
// Ensure we have enough data to operate on
input
=
common
.
RightPadBytes
(
input
,
96
)
p
,
err
:=
newCurvePoint
(
input
[
:
64
])
p
,
err
:=
newCurvePoint
(
getData
(
input
,
0
,
64
))
if
err
!=
nil
{
return
nil
,
err
}
p
.
ScalarMult
(
p
,
new
(
big
.
Int
)
.
SetBytes
(
input
[
64
:
96
]
))
p
.
ScalarMult
(
p
,
new
(
big
.
Int
)
.
SetBytes
(
getData
(
input
,
64
,
32
)
))
return
p
.
Marshal
(),
nil
}
...
...
core/vm/contracts_test.go
View file @
f8d8b56b
...
...
@@ -325,7 +325,7 @@ func TestPrecompiledBn256Pairing(t *testing.T) {
}
// Behcnmarks the sample inputs from the elliptic curve pairing check EIP 197.
func
BenchmarkPrecompiledPairing
(
bench
*
testing
.
B
)
{
func
BenchmarkPrecompiled
Bn256
Pairing
(
bench
*
testing
.
B
)
{
for
_
,
test
:=
range
bn256PairingTests
{
benchmarkPrecompiled
(
"08"
,
test
,
bench
)
}
...
...
core/vm/instructions.go
View file @
f8d8b56b
...
...
@@ -337,7 +337,7 @@ func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
}
func
opCalldataLoad
(
pc
*
uint64
,
evm
*
EVM
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
stack
.
push
(
new
(
big
.
Int
)
.
SetBytes
(
getData
(
contract
.
Input
,
stack
.
pop
(),
common
.
B
ig32
)))
stack
.
push
(
new
(
big
.
Int
)
.
SetBytes
(
getData
Big
(
contract
.
Input
,
stack
.
pop
(),
b
ig32
)))
return
nil
,
nil
}
...
...
@@ -352,7 +352,7 @@ func opCalldataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
cOff
=
stack
.
pop
()
l
=
stack
.
pop
()
)
memory
.
Set
(
mOff
.
Uint64
(),
l
.
Uint64
(),
getData
(
contract
.
Input
,
cOff
,
l
))
memory
.
Set
(
mOff
.
Uint64
(),
l
.
Uint64
(),
getData
Big
(
contract
.
Input
,
cOff
,
l
))
evm
.
interpreter
.
intPool
.
put
(
mOff
,
cOff
,
l
)
return
nil
,
nil
...
...
@@ -380,7 +380,7 @@ func opCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
cOff
=
stack
.
pop
()
l
=
stack
.
pop
()
)
codeCopy
:=
getData
(
contract
.
Code
,
cOff
,
l
)
codeCopy
:=
getData
Big
(
contract
.
Code
,
cOff
,
l
)
memory
.
Set
(
mOff
.
Uint64
(),
l
.
Uint64
(),
codeCopy
)
...
...
@@ -395,7 +395,7 @@ func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, sta
cOff
=
stack
.
pop
()
l
=
stack
.
pop
()
)
codeCopy
:=
getData
(
evm
.
StateDB
.
GetCode
(
addr
),
cOff
,
l
)
codeCopy
:=
getData
Big
(
evm
.
StateDB
.
GetCode
(
addr
),
cOff
,
l
)
memory
.
Set
(
mOff
.
Uint64
(),
l
.
Uint64
(),
codeCopy
)
...
...
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