@@ -10,6 +10,7 @@ import io.iohk.ethereum.utils.ByteUtils
10
10
import io .iohk .ethereum .vm .BlockchainConfigForEvm .EtcForks .EtcFork
11
11
import io .iohk .ethereum .vm .BlockchainConfigForEvm .EthForks .EthFork
12
12
import io .iohk .ethereum .vm .BlockchainConfigForEvm .{EtcForks , EthForks }
13
+
13
14
import scala .util .Try
14
15
15
16
// scalastyle:off magic.number
@@ -23,6 +24,7 @@ object PrecompiledContracts {
23
24
val Bn128AddAddr = Address (6 )
24
25
val Bn128MulAddr = Address (7 )
25
26
val Bn128PairingAddr = Address (8 )
27
+ val Blake2bCompressionAddr = Address (9 )
26
28
27
29
val contracts = Map (
28
30
EcDsaRecAddr -> EllipticCurveRecovery ,
@@ -37,6 +39,10 @@ object PrecompiledContracts {
37
39
Bn128MulAddr -> Bn128Mul ,
38
40
Bn128PairingAddr -> Bn128Pairing
39
41
)
42
+
43
+ val istanbulPhoenisContracts = byzantiumAtlantisContracts ++ Map (
44
+ Blake2bCompressionAddr -> Blake2bCompress
45
+ )
40
46
/**
41
47
* Checks whether `ProgramContext#recipientAddr` points to a precompiled contract
42
48
*/
@@ -53,8 +59,12 @@ object PrecompiledContracts {
53
59
54
60
private def getContract (context : ProgramContext [_, _]): Option [PrecompiledContract ] = {
55
61
context.recipientAddr.flatMap{ addr =>
56
- if (context.evmConfig.blockchainConfig.ethForkForBlockNumber(context.blockHeader.number) >= EthForks .Byzantium ||
57
- context.evmConfig.blockchainConfig.etcForkForBlockNumber(context.blockHeader.number) >= EtcForks .Atlantis ) {
62
+ val ethFork = context.evmConfig.blockchainConfig.ethForkForBlockNumber(context.blockHeader.number)
63
+ val etcFork = context.evmConfig.blockchainConfig.etcForkForBlockNumber(context.blockHeader.number)
64
+
65
+ if (ethFork >= EthForks .Istanbul || etcFork >= EtcForks .Phoenix ) {
66
+ istanbulPhoenisContracts.get(addr)
67
+ } else if (ethFork >= EthForks .Byzantium || etcFork >= EtcForks .Atlantis ) {
58
68
// byzantium and atlantis hard fork introduce the same set of precompiled contracts
59
69
byzantiumAtlantisContracts.get(addr)
60
70
} else
@@ -375,4 +385,23 @@ object PrecompiledContracts {
375
385
input.slice(from, from + wordLength)
376
386
}
377
387
}
388
+
389
+ // Spec: https://eips.ethereum.org/EIPS/eip-152
390
+ // scalastyle: off
391
+ object Blake2bCompress extends PrecompiledContract {
392
+ def exec (inputData : ByteString ): Option [ByteString ] = {
393
+ Blake2bCompression .blake2bCompress(inputData.toArray).map(ByteString .fromArrayUnsafe)
394
+ }
395
+
396
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt = {
397
+ val inputArray = inputData.toArray
398
+ if (Blake2bCompression .isValidInput(inputArray)) {
399
+ // Each round costs 1gas
400
+ Blake2bCompression .parseNumberOfRounds(inputArray)
401
+ } else {
402
+ // bad input to contract, contract will not execute, set price to zero
403
+ 0
404
+ }
405
+ }
406
+ }
378
407
}
0 commit comments