good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
bor
Commits
7bbdf3e2
Unverified
Commit
7bbdf3e2
authored
Aug 10, 2017
by
Jeffrey Wilcke
Committed by
Péter Szilágyi
Aug 11, 2017
Browse files
Options
Downloads
Patches
Plain Diff
core: add Metropolis pre-compiles (EIP 197, 198 and 213)
parent
6ca59d98
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
core/vm/contracts.go
+202
-0
202 additions, 0 deletions
core/vm/contracts.go
core/vm/contracts_test.go
+34
-0
34 additions, 0 deletions
core/vm/contracts_test.go
core/vm/evm.go
+6
-2
6 additions, 2 deletions
core/vm/evm.go
with
242 additions
and
2 deletions
core/vm/contracts.go
+
202
−
0
View file @
7bbdf3e2
...
...
@@ -22,7 +22,9 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/bn256"
"github.com/ethereum/go-ethereum/params"
"golang.org/x/crypto/ripemd160"
)
...
...
@@ -45,6 +47,19 @@ var PrecompiledContracts = map[common.Address]PrecompiledContract{
common
.
BytesToAddress
([]
byte
{
4
})
:
&
dataCopy
{},
}
// PrecompiledContractsMetropolis contains the default set of ethereum contracts
// for metropolis hardfork
var
PrecompiledContractsMetropolis
=
map
[
common
.
Address
]
PrecompiledContract
{
common
.
BytesToAddress
([]
byte
{
1
})
:
&
ecrecover
{},
common
.
BytesToAddress
([]
byte
{
2
})
:
&
sha256hash
{},
common
.
BytesToAddress
([]
byte
{
3
})
:
&
ripemd160hash
{},
common
.
BytesToAddress
([]
byte
{
4
})
:
&
dataCopy
{},
common
.
BytesToAddress
([]
byte
{
5
})
:
&
bigModexp
{},
common
.
BytesToAddress
([]
byte
{
6
})
:
&
bn256Add
{},
common
.
BytesToAddress
([]
byte
{
7
})
:
&
bn256ScalarMul
{},
common
.
BytesToAddress
([]
byte
{
8
})
:
&
pairing
{},
}
// RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
func
RunPrecompiledContract
(
p
PrecompiledContract
,
input
[]
byte
,
contract
*
Contract
)
(
ret
[]
byte
,
err
error
)
{
gas
:=
p
.
RequiredGas
(
input
)
...
...
@@ -132,3 +147,190 @@ func (c *dataCopy) RequiredGas(input []byte) uint64 {
func
(
c
*
dataCopy
)
Run
(
in
[]
byte
)
([]
byte
,
error
)
{
return
in
,
nil
}
// bigModexp implements a native big integer exponential modular operation.
type
bigModexp
struct
{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
func
(
c
*
bigModexp
)
RequiredGas
(
input
[]
byte
)
uint64
{
// TODO reword required gas to have error reporting and convert arithmetic
// to uint64.
if
len
(
input
)
<
3
*
32
{
input
=
append
(
input
,
make
([]
byte
,
3
*
32
-
len
(
input
))
...
)
}
var
(
baseLen
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
:
31
])
expLen
=
math
.
BigMax
(
new
(
big
.
Int
)
.
SetBytes
(
input
[
32
:
64
]),
big
.
NewInt
(
1
))
modLen
=
new
(
big
.
Int
)
.
SetBytes
(
input
[
65
:
97
])
)
x
:=
new
(
big
.
Int
)
.
Set
(
math
.
BigMax
(
baseLen
,
modLen
))
x
.
Mul
(
x
,
x
)
x
.
Mul
(
x
,
expLen
)
x
.
Div
(
x
,
new
(
big
.
Int
)
.
SetUint64
(
params
.
QuadCoeffDiv
))
return
x
.
Uint64
()
}
func
(
c
*
bigModexp
)
Run
(
input
[]
byte
)
([]
byte
,
error
)
{
if
len
(
input
)
<
3
*
32
{
input
=
append
(
input
,
make
([]
byte
,
3
*
32
-
len
(
input
))
...
)
}
// why 32-byte? These values won't fit anyway
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
()
)
input
=
input
[
96
:
]
if
uint64
(
len
(
input
))
<
baseLen
{
input
=
append
(
input
,
make
([]
byte
,
baseLen
-
uint64
(
len
(
input
)))
...
)
}
base
:=
new
(
big
.
Int
)
.
SetBytes
(
input
[
:
baseLen
])
input
=
input
[
baseLen
:
]
if
uint64
(
len
(
input
))
<
expLen
{
input
=
append
(
input
,
make
([]
byte
,
expLen
-
uint64
(
len
(
input
)))
...
)
}
exp
:=
new
(
big
.
Int
)
.
SetBytes
(
input
[
:
expLen
])
input
=
input
[
expLen
:
]
if
uint64
(
len
(
input
))
<
modLen
{
input
=
append
(
input
,
make
([]
byte
,
modLen
-
uint64
(
len
(
input
)))
...
)
}
mod
:=
new
(
big
.
Int
)
.
SetBytes
(
input
[
:
modLen
])
return
common
.
LeftPadBytes
(
base
.
Exp
(
base
,
exp
,
mod
)
.
Bytes
(),
len
(
input
[
:
modLen
])),
nil
}
type
bn256Add
struct
{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
func
(
c
*
bn256Add
)
RequiredGas
(
input
[]
byte
)
uint64
{
return
0
// TODO
}
func
(
c
*
bn256Add
)
Run
(
in
[]
byte
)
([]
byte
,
error
)
{
in
=
common
.
RightPadBytes
(
in
,
128
)
x
,
onCurve
:=
new
(
bn256
.
G1
)
.
Unmarshal
(
in
[
:
64
])
if
!
onCurve
{
return
nil
,
errNotOnCurve
}
gx
,
gy
,
_
,
_
:=
x
.
CurvePoints
()
if
gx
.
Cmp
(
bn256
.
P
)
>=
0
||
gy
.
Cmp
(
bn256
.
P
)
>=
0
{
return
nil
,
errInvalidCurvePoint
}
y
,
onCurve
:=
new
(
bn256
.
G1
)
.
Unmarshal
(
in
[
64
:
128
])
if
!
onCurve
{
return
nil
,
errNotOnCurve
}
gx
,
gy
,
_
,
_
=
y
.
CurvePoints
()
if
gx
.
Cmp
(
bn256
.
P
)
>=
0
||
gy
.
Cmp
(
bn256
.
P
)
>=
0
{
return
nil
,
errInvalidCurvePoint
}
x
.
Add
(
x
,
y
)
return
x
.
Marshal
(),
nil
}
type
bn256ScalarMul
struct
{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
func
(
c
*
bn256ScalarMul
)
RequiredGas
(
input
[]
byte
)
uint64
{
return
0
// TODO
}
func
(
c
*
bn256ScalarMul
)
Run
(
in
[]
byte
)
([]
byte
,
error
)
{
in
=
common
.
RightPadBytes
(
in
,
96
)
g1
,
onCurve
:=
new
(
bn256
.
G1
)
.
Unmarshal
(
in
[
:
64
])
if
!
onCurve
{
return
nil
,
errNotOnCurve
}
x
,
y
,
_
,
_
:=
g1
.
CurvePoints
()
if
x
.
Cmp
(
bn256
.
P
)
>=
0
||
y
.
Cmp
(
bn256
.
P
)
>=
0
{
return
nil
,
errInvalidCurvePoint
}
g1
.
ScalarMult
(
g1
,
new
(
big
.
Int
)
.
SetBytes
(
in
[
64
:
96
]))
return
g1
.
Marshal
(),
nil
}
// pairing implements a pairing pre-compile for the bn256 curve
type
pairing
struct
{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
func
(
c
*
pairing
)
RequiredGas
(
input
[]
byte
)
uint64
{
//return 0 // TODO
k
:=
(
len
(
input
)
+
191
)
/
pairSize
return
uint64
(
60000
*
k
+
40000
)
}
const
pairSize
=
192
var
(
true32Byte
=
[]
byte
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
}
fals32Byte
=
make
([]
byte
,
32
)
errNotOnCurve
=
errors
.
New
(
"point not on elliptic curve"
)
errInvalidCurvePoint
=
errors
.
New
(
"invalid elliptic curve point"
)
)
func
(
c
*
pairing
)
Run
(
in
[]
byte
)
([]
byte
,
error
)
{
if
len
(
in
)
==
0
{
return
true32Byte
,
nil
}
if
len
(
in
)
%
pairSize
>
0
{
return
nil
,
errBadPrecompileInput
}
var
(
g1s
[]
*
bn256
.
G1
g2s
[]
*
bn256
.
G2
)
for
i
:=
0
;
i
<
len
(
in
);
i
+=
pairSize
{
g1
,
onCurve
:=
new
(
bn256
.
G1
)
.
Unmarshal
(
in
[
i
:
i
+
64
])
if
!
onCurve
{
return
nil
,
errNotOnCurve
}
x
,
y
,
_
,
_
:=
g1
.
CurvePoints
()
if
x
.
Cmp
(
bn256
.
P
)
>=
0
||
y
.
Cmp
(
bn256
.
P
)
>=
0
{
return
nil
,
errInvalidCurvePoint
}
g2
,
onCurve
:=
new
(
bn256
.
G2
)
.
Unmarshal
(
in
[
i
+
64
:
i
+
192
])
if
!
onCurve
{
return
nil
,
errNotOnCurve
}
x2
,
y2
,
_
,
_
:=
g2
.
CurvePoints
()
if
x2
.
Real
()
.
Cmp
(
bn256
.
P
)
>=
0
||
x2
.
Imag
()
.
Cmp
(
bn256
.
P
)
>=
0
||
y2
.
Real
()
.
Cmp
(
bn256
.
P
)
>=
0
||
y2
.
Imag
()
.
Cmp
(
bn256
.
P
)
>=
0
{
return
nil
,
errInvalidCurvePoint
}
g1s
=
append
(
g1s
,
g1
)
g2s
=
append
(
g2s
,
g2
)
}
isOne
:=
bn256
.
PairingCheck
(
g1s
,
g2s
)
if
isOne
{
return
true32Byte
,
nil
}
return
fals32Byte
,
nil
}
This diff is collapsed.
Click to expand it.
core/vm/contracts_test.go
+
34
−
0
View file @
7bbdf3e2
package
vm
import
(
"testing"
"github.com/ethereum/go-ethereum/common"
)
const
input
=
""
func
TestPairing
(
t
*
testing
.
T
)
{
pairing
:=
&
pairing
{}
for
i
,
test
:=
range
[]
struct
{
input
string
valid
int
}{
{
"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
,
1
},
{
"2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
,
1
},
{
"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
,
1
},
{
"2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f"
,
1
},
{
"20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
,
1
},
{
"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
,
0
},
}
{
r
,
err
:=
pairing
.
Run
(
common
.
FromHex
(
test
.
input
))
if
err
!=
nil
{
t
.
Error
(
i
,
":"
,
err
)
}
if
int
(
r
[
31
])
!=
test
.
valid
{
t
.
Error
(
i
,
"expected"
,
test
.
valid
,
"but was"
,
r
[
31
])
}
}
}
This diff is collapsed.
Click to expand it.
core/vm/evm.go
+
6
−
2
View file @
7bbdf3e2
...
...
@@ -37,6 +37,10 @@ type (
func
run
(
evm
*
EVM
,
snapshot
int
,
contract
*
Contract
,
input
[]
byte
)
([]
byte
,
error
)
{
if
contract
.
CodeAddr
!=
nil
{
precompiledContracts
:=
PrecompiledContracts
if
evm
.
ChainConfig
()
.
IsMetropolis
(
evm
.
BlockNumber
)
{
precompiledContracts
=
PrecompiledContractsMetropolis
}
if
p
:=
precompiledContracts
[
*
contract
.
CodeAddr
];
p
!=
nil
{
return
RunPrecompiledContract
(
p
,
input
,
contract
)
}
...
...
@@ -100,8 +104,8 @@ type EVM struct {
abort
int32
}
// NewEVM retutrns a new EVM
evmironment
. The returned EVM is not thread safe
//
and should
only ever be used *once*.
// NewEVM retutrns a new EVM . The returned EVM is not thread safe
and should
// only ever be used *once*.
func
NewEVM
(
ctx
Context
,
statedb
StateDB
,
chainConfig
*
params
.
ChainConfig
,
vmConfig
Config
)
*
EVM
{
evm
:=
&
EVM
{
Context
:
ctx
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment