Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
7bbdf3e2
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
7bbdf3e2
编写于
8月 10, 2017
作者:
J
Jeffrey Wilcke
提交者:
Péter Szilágyi
8月 11, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
core: add Metropolis pre-compiles (EIP 197, 198 and 213)
上级
6ca59d98
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
242 addition
and
2 deletion
+242
-2
core/vm/contracts.go
core/vm/contracts.go
+202
-0
core/vm/contracts_test.go
core/vm/contracts_test.go
+34
-0
core/vm/evm.go
core/vm/evm.go
+6
-2
未找到文件。
core/vm/contracts.go
浏览文件 @
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
}
core/vm/contracts_test.go
浏览文件 @
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
])
}
}
}
core/vm/evm.go
浏览文件 @
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
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录