|
1 | 1 | package org.tron.core.vm; |
2 | 2 |
|
3 | 3 | import static java.util.Arrays.copyOfRange; |
| 4 | +import static org.tron.common.crypto.ckzg4844.CKZG4844JNI.BLS_MODULUS; |
| 5 | +import static org.tron.common.crypto.ckzg4844.CKZG4844JNI.FIELD_ELEMENTS_PER_BLOB; |
4 | 6 | import static org.tron.common.math.Maths.max; |
5 | 7 | import static org.tron.common.math.Maths.min; |
6 | 8 | import static org.tron.common.runtime.vm.DataWord.WORD_SIZE; |
|
32 | 34 | import java.util.concurrent.ExecutorService; |
33 | 35 | import java.util.concurrent.Future; |
34 | 36 | import java.util.concurrent.TimeUnit; |
| 37 | +import org.tron.common.crypto.ckzg4844.CKZG4844JNI; |
35 | 38 | import lombok.AllArgsConstructor; |
36 | 39 | import lombok.Getter; |
37 | 40 | import lombok.Setter; |
@@ -104,6 +107,7 @@ public class PrecompiledContracts { |
104 | 107 |
|
105 | 108 | private static final EthRipemd160 ethRipemd160 = new EthRipemd160(); |
106 | 109 | private static final Blake2F blake2F = new Blake2F(); |
| 110 | + private static final KZGPointEvaluation kzgPointEvaluation = new KZGPointEvaluation(); |
107 | 111 |
|
108 | 112 | // FreezeV2 PrecompileContracts |
109 | 113 | private static final GetChainParameter getChainParameter = new GetChainParameter(); |
@@ -198,6 +202,9 @@ public class PrecompiledContracts { |
198 | 202 | private static final DataWord blake2FAddr = new DataWord( |
199 | 203 | "0000000000000000000000000000000000000000000000000000000000020009"); |
200 | 204 |
|
| 205 | + private static final DataWord kzgPointEvaluationAddr = new DataWord( |
| 206 | + "000000000000000000000000000000000000000000000000000000000002000a"); |
| 207 | + |
201 | 208 | public static PrecompiledContract getOptimizedContractForConstant(PrecompiledContract contract) { |
202 | 209 | try { |
203 | 210 | Constructor<?> constructor = contract.getClass().getDeclaredConstructor(); |
@@ -279,6 +286,9 @@ public static PrecompiledContract getContractForAddress(DataWord address) { |
279 | 286 | if (VMConfig.allowTvmCompatibleEvm() && address.equals(blake2FAddr)) { |
280 | 287 | return blake2F; |
281 | 288 | } |
| 289 | + if (VMConfig.allowTvmBlob() && address.equals(kzgPointEvaluationAddr)) { |
| 290 | + return kzgPointEvaluation; |
| 291 | + } |
282 | 292 |
|
283 | 293 | if (VMConfig.allowTvmFreezeV2()) { |
284 | 294 | if (address.equals(getChainParameterAddr)) { |
@@ -2191,4 +2201,49 @@ public Pair<Boolean, byte[]> execute(byte[] data) { |
2191 | 2201 | } |
2192 | 2202 | } |
2193 | 2203 |
|
| 2204 | + public static class KZGPointEvaluation extends PrecompiledContract { |
| 2205 | + |
| 2206 | + private static final int BLOB_VERIFY_INPUT_LENGTH = 192; |
| 2207 | + private static final byte BLOB_COMMITMENT_VERSION_KZG = 0x01; |
| 2208 | + private static final byte[] BLOB_PRECOMPILED_RETURN_VALUE = |
| 2209 | + ByteUtil.merge(ByteUtil.longTo32Bytes(FIELD_ELEMENTS_PER_BLOB), |
| 2210 | + ByteUtil.bigIntegerToBytes(BLS_MODULUS, 32)); |
| 2211 | + |
| 2212 | + @Override |
| 2213 | + public long getEnergyForData(byte[] data) { |
| 2214 | + return 50000; |
| 2215 | + } |
| 2216 | + |
| 2217 | + @Override |
| 2218 | + public Pair<Boolean, byte[]> execute(byte[] data) { |
| 2219 | + if (data == null || data.length != BLOB_VERIFY_INPUT_LENGTH) { |
| 2220 | + return Pair.of(false, DataWord.ZERO().getData()); |
| 2221 | + } |
| 2222 | + |
| 2223 | + byte[] versionedHash = parseBytes(data, 0, 32); |
| 2224 | + byte[] z = parseBytes(data, 32, 32); |
| 2225 | + byte[] y = parseBytes(data, 64, 32); |
| 2226 | + byte[] commitment = parseBytes(data, 96, 48); |
| 2227 | + byte[] proof = parseBytes(data, 144, 48); |
| 2228 | + |
| 2229 | + byte[] hash = Sha256Hash.hash( |
| 2230 | + CommonParameter.getInstance().isECKeyCryptoEngine(), commitment); |
| 2231 | + hash[0] = BLOB_COMMITMENT_VERSION_KZG; |
| 2232 | + if (!Arrays.equals(versionedHash, hash)) { |
| 2233 | + return Pair.of(false, DataWord.ZERO().getData()); |
| 2234 | + } |
| 2235 | + |
| 2236 | + try { |
| 2237 | + if (CKZG4844JNI.verifyKzgProof(commitment, z, y, proof)) { |
| 2238 | + return Pair.of(true, BLOB_PRECOMPILED_RETURN_VALUE); |
| 2239 | + } else { |
| 2240 | + return Pair.of(false, DataWord.ZERO().getData()); |
| 2241 | + } |
| 2242 | + } catch (RuntimeException exception) { |
| 2243 | + logger.warn("KZG point evaluation precompile contract failed", exception); |
| 2244 | + return Pair.of(false, DataWord.ZERO().getData()); |
| 2245 | + } |
| 2246 | + } |
| 2247 | + } |
| 2248 | + |
2194 | 2249 | } |
0 commit comments