@@ -10,6 +10,7 @@ import io.iohk.ethereum.utils.ByteUtils
1010import io .iohk .ethereum .vm .BlockchainConfigForEvm .EtcForks .EtcFork
1111import io .iohk .ethereum .vm .BlockchainConfigForEvm .EthForks .EthFork
1212import io .iohk .ethereum .vm .BlockchainConfigForEvm .{EtcForks , EthForks }
13+
1314import scala .util .Try
1415
1516// scalastyle:off magic.number
@@ -23,6 +24,7 @@ object PrecompiledContracts {
2324 val Bn128AddAddr = Address (6 )
2425 val Bn128MulAddr = Address (7 )
2526 val Bn128PairingAddr = Address (8 )
27+ val Blake2bCompressionAddr = Address (9 )
2628
2729 val contracts = Map (
2830 EcDsaRecAddr -> EllipticCurveRecovery ,
@@ -37,6 +39,10 @@ object PrecompiledContracts {
3739 Bn128MulAddr -> Bn128Mul ,
3840 Bn128PairingAddr -> Bn128Pairing
3941 )
42+
43+ val istanbulPhoenisContracts = byzantiumAtlantisContracts ++ Map (
44+ Blake2bCompressionAddr -> Blake2bCompress
45+ )
4046 /**
4147 * Checks whether `ProgramContext#recipientAddr` points to a precompiled contract
4248 */
@@ -53,8 +59,12 @@ object PrecompiledContracts {
5359
5460 private def getContract (context : ProgramContext [_, _]): Option [PrecompiledContract ] = {
5561 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 ) {
5868 // byzantium and atlantis hard fork introduce the same set of precompiled contracts
5969 byzantiumAtlantisContracts.get(addr)
6070 } else
@@ -375,4 +385,23 @@ object PrecompiledContracts {
375385 input.slice(from, from + wordLength)
376386 }
377387 }
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+ }
378407}
0 commit comments