|
8 | 8 | import com.google.protobuf.Any; |
9 | 9 | import com.google.protobuf.ByteString; |
10 | 10 | import com.google.protobuf.InvalidProtocolBufferException; |
| 11 | +import java.lang.reflect.Field; |
11 | 12 | import java.security.SignatureException; |
12 | 13 | import java.util.Arrays; |
13 | 14 | import java.util.HashSet; |
|
45 | 46 | import org.tron.common.zksnark.LibrustzcashParam.IvkToPkdParams; |
46 | 47 | import org.tron.common.zksnark.LibrustzcashParam.OutputProofParams; |
47 | 48 | import org.tron.common.zksnark.LibrustzcashParam.SpendSigParams; |
| 49 | +import org.tron.consensus.dpos.DposSlot; |
| 50 | +import org.tron.consensus.dpos.DposTask; |
48 | 51 | import org.tron.core.Wallet; |
49 | 52 | import org.tron.core.actuator.Actuator; |
50 | 53 | import org.tron.core.actuator.ActuatorCreator; |
@@ -140,14 +143,16 @@ public class ShieldedReceiveTest extends BaseTest { |
140 | 143 | @Resource |
141 | 144 | private ConsensusService consensusService; |
142 | 145 | @Resource |
| 146 | + private DposTask dposTask; |
| 147 | + @Resource |
143 | 148 | private Wallet wallet; |
144 | 149 | @Resource |
145 | | - private TransactionUtil transactionUtil; |
| 150 | + private DposSlot dposSlot; |
146 | 151 |
|
147 | 152 | private static boolean init; |
148 | 153 |
|
149 | 154 | static { |
150 | | - Args.setParam(new String[]{"--output-directory", dbPath(), "-w"}, SHIELD_CONF); |
| 155 | + Args.setParam(new String[] {"--output-directory", dbPath(), "-w"}, SHIELD_CONF); |
151 | 156 | ADDRESS_ONE_PRIVATE_KEY = getRandomPrivateKey(); |
152 | 157 | FROM_ADDRESS = getHexAddressByPrivateKey(ADDRESS_ONE_PRIVATE_KEY); |
153 | 158 | } |
@@ -331,7 +336,7 @@ public void testBroadcastBeforeAllowZksnark() |
331 | 336 |
|
332 | 337 | //Add public address sign |
333 | 338 | transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), |
334 | | - ADDRESS_ONE_PRIVATE_KEY, chainBaseManager.getAccountStore()); |
| 339 | + ADDRESS_ONE_PRIVATE_KEY, chainBaseManager.getAccountStore()); |
335 | 340 | try { |
336 | 341 | dbManager.pushTransaction(transactionCap); |
337 | 342 | } catch (Exception e) { |
@@ -433,7 +438,7 @@ public String[] generateSpendAndOutputParams() throws ZksnarkException, BadItemE |
433 | 438 | boolean ok2 = JLibrustzcash.librustzcashSaplingCheckOutput(checkOutputParams); |
434 | 439 | Assert.assertTrue(ok2); |
435 | 440 |
|
436 | | - return new String[]{ByteArray.toHexString(checkSpendParamsData), |
| 441 | + return new String[] {ByteArray.toHexString(checkSpendParamsData), |
437 | 442 | ByteArray.toHexString(dataToBeSigned), |
438 | 443 | ByteArray.toHexString(checkOutputParams.encode())}; |
439 | 444 | } |
@@ -2402,128 +2407,158 @@ public void pushSameSkAndScanAndSpend() throws Exception { |
2402 | 2407 | assert ecKey != null; |
2403 | 2408 | byte[] witnessAddress = ecKey.getAddress(); |
2404 | 2409 | WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(witnessAddress)); |
2405 | | - chainBaseManager.addWitness(ByteString.copyFrom(witnessAddress)); |
2406 | | - |
2407 | | - //sometimes generate block failed, try several times. |
2408 | | - long time = System.currentTimeMillis(); |
2409 | | - Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey); |
2410 | | - dbManager.pushBlock(new BlockCapsule(block)); |
2411 | | - |
2412 | | - //create transactions |
2413 | | - chainBaseManager.getDynamicPropertiesStore().saveAllowShieldedTransaction(1); |
2414 | | - chainBaseManager.getDynamicPropertiesStore().saveTotalShieldedPoolValue(1000 * 1000000L); |
2415 | | - ZenTransactionBuilder builder = new ZenTransactionBuilder(wallet); |
2416 | | - |
2417 | | - // generate spend proof |
2418 | | - SpendingKey sk = SpendingKey |
2419 | | - .decode("ff2c06269315333a9207f817d2eca0ac555ca8f90196976324c7756504e7c9ee"); |
2420 | | - ExpandedSpendingKey expsk = sk.expandedSpendingKey(); |
2421 | | - byte[] senderOvk = expsk.getOvk(); |
2422 | | - PaymentAddress address = sk.defaultAddress(); |
2423 | | - Note note = new Note(address, 1000 * 1000000L); |
2424 | | - IncrementalMerkleVoucherContainer voucher = createSimpleMerkleVoucherContainer(note.cm()); |
2425 | | - byte[] anchor = voucher.root().getContent().toByteArray(); |
2426 | | - chainBaseManager.getMerkleContainer() |
2427 | | - .putMerkleTreeIntoStore(anchor, voucher.getVoucherCapsule().getTree()); |
2428 | | - builder.addSpend(expsk, note, anchor, voucher); |
2429 | | - |
2430 | | - // generate output proof |
2431 | | - SpendingKey sk2 = SpendingKey.random(); |
2432 | | - FullViewingKey fullViewingKey = sk2.fullViewingKey(); |
2433 | | - IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); |
2434 | | - |
2435 | | - byte[] memo = org.tron.keystore.Wallet.generateRandomBytes(512); |
2436 | | - |
2437 | | - //send coin to 2 different address generated by same sk |
2438 | | - DiversifierT d1 = DiversifierT.random(); |
2439 | | - PaymentAddress paymentAddress1 = incomingViewingKey.address(d1).get(); |
2440 | | - builder.addOutput(senderOvk, paymentAddress1, |
2441 | | - (1000 * 1000000L - wallet.getShieldedTransactionFee()) / 2, memo); |
2442 | | - |
2443 | | - DiversifierT d2 = DiversifierT.random(); |
2444 | | - PaymentAddress paymentAddress2 = incomingViewingKey.address(d2).get(); |
2445 | | - builder.addOutput(senderOvk, paymentAddress2, |
2446 | | - (1000 * 1000000L - wallet.getShieldedTransactionFee()) / 2, memo); |
2447 | | - |
2448 | | - TransactionCapsule transactionCap = builder.build(); |
| 2410 | + // Stop the consensus task before modifying the witness schedule: DposTask uses the same |
| 2411 | + // localwitness key and would otherwise race to produce blocks at the same slot, |
| 2412 | + // triggering fork resolution and making the test slow. |
| 2413 | + consensusService.stop(); |
| 2414 | + try { |
| 2415 | + chainBaseManager.addWitness(ByteString.copyFrom(witnessAddress)); |
| 2416 | + |
| 2417 | + long time = nextScheduledTime(witnessCapsule.getAddress()); |
| 2418 | + Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey); |
| 2419 | + dbManager.pushBlock(new BlockCapsule(block)); |
| 2420 | + |
| 2421 | + //create transactions |
| 2422 | + chainBaseManager.getDynamicPropertiesStore().saveAllowShieldedTransaction(1); |
| 2423 | + chainBaseManager.getDynamicPropertiesStore().saveTotalShieldedPoolValue(1000 * 1000000L); |
| 2424 | + ZenTransactionBuilder builder = new ZenTransactionBuilder(wallet); |
| 2425 | + |
| 2426 | + // generate spend proof |
| 2427 | + SpendingKey sk = SpendingKey |
| 2428 | + .decode("ff2c06269315333a9207f817d2eca0ac555ca8f90196976324c7756504e7c9ee"); |
| 2429 | + ExpandedSpendingKey expsk = sk.expandedSpendingKey(); |
| 2430 | + byte[] senderOvk = expsk.getOvk(); |
| 2431 | + PaymentAddress address = sk.defaultAddress(); |
| 2432 | + Note note = new Note(address, 1000 * 1000000L); |
| 2433 | + IncrementalMerkleVoucherContainer voucher = createSimpleMerkleVoucherContainer(note.cm()); |
| 2434 | + byte[] anchor = voucher.root().getContent().toByteArray(); |
| 2435 | + chainBaseManager.getMerkleContainer() |
| 2436 | + .putMerkleTreeIntoStore(anchor, voucher.getVoucherCapsule().getTree()); |
| 2437 | + builder.addSpend(expsk, note, anchor, voucher); |
| 2438 | + |
| 2439 | + // generate output proof |
| 2440 | + SpendingKey sk2 = SpendingKey.random(); |
| 2441 | + FullViewingKey fullViewingKey = sk2.fullViewingKey(); |
| 2442 | + IncomingViewingKey incomingViewingKey = fullViewingKey.inViewingKey(); |
| 2443 | + |
| 2444 | + byte[] memo = org.tron.keystore.Wallet.generateRandomBytes(512); |
| 2445 | + |
| 2446 | + //send coin to 2 different address generated by same sk |
| 2447 | + DiversifierT d1 = DiversifierT.random(); |
| 2448 | + PaymentAddress paymentAddress1 = incomingViewingKey.address(d1).get(); |
| 2449 | + builder.addOutput(senderOvk, paymentAddress1, |
| 2450 | + (1000 * 1000000L - wallet.getShieldedTransactionFee()) / 2, memo); |
| 2451 | + |
| 2452 | + DiversifierT d2 = DiversifierT.random(); |
| 2453 | + PaymentAddress paymentAddress2 = incomingViewingKey.address(d2).get(); |
| 2454 | + builder.addOutput(senderOvk, paymentAddress2, |
| 2455 | + (1000 * 1000000L - wallet.getShieldedTransactionFee()) / 2, memo); |
2449 | 2456 |
|
2450 | | - byte[] trxId = transactionCap.getTransactionId().getBytes(); |
2451 | | - boolean ok = dbManager.pushTransaction(transactionCap); |
2452 | | - Assert.assertTrue(ok); |
| 2457 | + TransactionCapsule transactionCap = builder.build(); |
2453 | 2458 |
|
2454 | | - Thread.sleep(500); |
2455 | | - //package transaction to block |
2456 | | - block = getSignedBlock(witnessCapsule.getAddress(), time + 3000, privateKey); |
2457 | | - dbManager.pushBlock(new BlockCapsule(block)); |
2458 | | - |
2459 | | - BlockCapsule blockCapsule3 = new BlockCapsule(wallet.getNowBlock()); |
2460 | | - Assert.assertEquals("blocknum != 2", 2, blockCapsule3.getNum()); |
2461 | | - |
2462 | | - block = getSignedBlock(witnessCapsule.getAddress(), time + 6000, privateKey); |
2463 | | - dbManager.pushBlock(new BlockCapsule(block)); |
2464 | | - |
2465 | | - // scan note by ivk |
2466 | | - byte[] receiverIvk = incomingViewingKey.getValue(); |
2467 | | - DecryptNotes notes1 = wallet.scanNoteByIvk(0, 100, receiverIvk); |
2468 | | - Assert.assertEquals(2, notes1.getNoteTxsCount()); |
2469 | | - |
2470 | | - // scan note by ivk and mark |
2471 | | - DecryptNotesMarked notes3 = wallet.scanAndMarkNoteByIvk(0, 100, receiverIvk, |
2472 | | - fullViewingKey.getAk(), fullViewingKey.getNk()); |
2473 | | - Assert.assertEquals(2, notes3.getNoteTxsCount()); |
2474 | | - |
2475 | | - // scan note by ovk |
2476 | | - DecryptNotes notes2 = wallet.scanNoteByOvk(0, 100, senderOvk); |
2477 | | - Assert.assertEquals(2, notes2.getNoteTxsCount()); |
2478 | | - |
2479 | | - // to spend received note above. |
2480 | | - ZenTransactionBuilder builder2 = new ZenTransactionBuilder(wallet); |
2481 | | - |
2482 | | - //query merkleinfo |
2483 | | - OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); |
2484 | | - for (int i = 0; i < notes1.getNoteTxsCount(); i++) { |
2485 | | - OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); |
2486 | | - outPointBuild.setHash(ByteString.copyFrom(trxId)); |
2487 | | - outPointBuild.setIndex(i); |
2488 | | - request.addOutPoints(outPointBuild.build()); |
2489 | | - } |
2490 | | - request.setBlockNum(1); |
2491 | | - IncrementalMerkleVoucherInfo merkleVoucherInfo = wallet |
2492 | | - .getMerkleTreeVoucherInfo(request.build()); |
2493 | | - |
2494 | | - //build spend proof. allow only one note in spend |
2495 | | - ExpandedSpendingKey expsk2 = sk2.expandedSpendingKey(); |
2496 | | - for (int i = 0; i < 1; i++) { |
2497 | | - org.tron.api.GrpcAPI.Note grpcNote = notes1.getNoteTxs(i).getNote(); |
2498 | | - PaymentAddress paymentAddress = KeyIo.decodePaymentAddress(grpcNote.getPaymentAddress()); |
2499 | | - Note note2 = new Note(paymentAddress.getD(), |
2500 | | - paymentAddress.getPkD(), |
2501 | | - grpcNote.getValue(), |
2502 | | - grpcNote.getRcm().toByteArray() |
2503 | | - ); |
| 2459 | + byte[] trxId = transactionCap.getTransactionId().getBytes(); |
| 2460 | + boolean ok = dbManager.pushTransaction(transactionCap); |
| 2461 | + Assert.assertTrue(ok); |
| 2462 | + |
| 2463 | + Thread.sleep(500); |
| 2464 | + //package transaction to block |
| 2465 | + long expectedBlockNum = chainBaseManager.getDynamicPropertiesStore() |
| 2466 | + .getLatestBlockHeaderNumber() + 1; |
| 2467 | + block = getSignedBlock(witnessCapsule.getAddress(), |
| 2468 | + nextScheduledTime(witnessCapsule.getAddress()), privateKey); |
| 2469 | + dbManager.pushBlock(new BlockCapsule(block)); |
| 2470 | + |
| 2471 | + BlockCapsule blockCapsule3 = new BlockCapsule(wallet.getNowBlock()); |
| 2472 | + Assert.assertEquals("unexpected block number", expectedBlockNum, blockCapsule3.getNum()); |
| 2473 | + |
| 2474 | + block = getSignedBlock(witnessCapsule.getAddress(), |
| 2475 | + nextScheduledTime(witnessCapsule.getAddress()), privateKey); |
| 2476 | + dbManager.pushBlock(new BlockCapsule(block)); |
| 2477 | + |
| 2478 | + // scan note by ivk |
| 2479 | + byte[] receiverIvk = incomingViewingKey.getValue(); |
| 2480 | + DecryptNotes notes1 = wallet.scanNoteByIvk(0, 100, receiverIvk); |
| 2481 | + Assert.assertEquals(2, notes1.getNoteTxsCount()); |
| 2482 | + |
| 2483 | + // scan note by ivk and mark |
| 2484 | + DecryptNotesMarked notes3 = wallet.scanAndMarkNoteByIvk(0, 100, receiverIvk, |
| 2485 | + fullViewingKey.getAk(), fullViewingKey.getNk()); |
| 2486 | + Assert.assertEquals(2, notes3.getNoteTxsCount()); |
| 2487 | + |
| 2488 | + // scan note by ovk |
| 2489 | + DecryptNotes notes2 = wallet.scanNoteByOvk(0, 100, senderOvk); |
| 2490 | + Assert.assertEquals(2, notes2.getNoteTxsCount()); |
| 2491 | + |
| 2492 | + // to spend received note above. |
| 2493 | + ZenTransactionBuilder builder2 = new ZenTransactionBuilder(wallet); |
| 2494 | + |
| 2495 | + //query merkleinfo |
| 2496 | + OutputPointInfo.Builder request = OutputPointInfo.newBuilder(); |
| 2497 | + for (int i = 0; i < notes1.getNoteTxsCount(); i++) { |
| 2498 | + OutputPoint.Builder outPointBuild = OutputPoint.newBuilder(); |
| 2499 | + outPointBuild.setHash(ByteString.copyFrom(trxId)); |
| 2500 | + outPointBuild.setIndex(i); |
| 2501 | + request.addOutPoints(outPointBuild.build()); |
| 2502 | + } |
| 2503 | + request.setBlockNum(1); |
| 2504 | + IncrementalMerkleVoucherInfo merkleVoucherInfo = wallet |
| 2505 | + .getMerkleTreeVoucherInfo(request.build()); |
| 2506 | + |
| 2507 | + //build spend proof. allow only one note in spend |
| 2508 | + ExpandedSpendingKey expsk2 = sk2.expandedSpendingKey(); |
| 2509 | + for (int i = 0; i < 1; i++) { |
| 2510 | + org.tron.api.GrpcAPI.Note grpcNote = notes1.getNoteTxs(i).getNote(); |
| 2511 | + PaymentAddress paymentAddress = KeyIo.decodePaymentAddress(grpcNote.getPaymentAddress()); |
| 2512 | + Note note2 = new Note(paymentAddress.getD(), |
| 2513 | + paymentAddress.getPkD(), |
| 2514 | + grpcNote.getValue(), |
| 2515 | + grpcNote.getRcm().toByteArray() |
| 2516 | + ); |
| 2517 | + |
| 2518 | + IncrementalMerkleVoucherContainer voucher2 = |
| 2519 | + new IncrementalMerkleVoucherContainer( |
| 2520 | + new IncrementalMerkleVoucherCapsule(merkleVoucherInfo.getVouchers(i))); |
| 2521 | + byte[] anchor2 = voucher2.root().getContent().toByteArray(); |
| 2522 | + builder2.addSpend(expsk2, note2, anchor2, voucher2); |
| 2523 | + } |
2504 | 2524 |
|
2505 | | - IncrementalMerkleVoucherContainer voucher2 = |
2506 | | - new IncrementalMerkleVoucherContainer( |
2507 | | - new IncrementalMerkleVoucherCapsule(merkleVoucherInfo.getVouchers(i))); |
2508 | | - byte[] anchor2 = voucher2.root().getContent().toByteArray(); |
2509 | | - builder2.addSpend(expsk2, note2, anchor2, voucher2); |
| 2525 | + //build output proof |
| 2526 | + SpendingKey sk3 = SpendingKey.random(); |
| 2527 | + FullViewingKey fvk3 = sk3.fullViewingKey(); |
| 2528 | + IncomingViewingKey ivk3 = fvk3.inViewingKey(); |
| 2529 | + |
| 2530 | + DiversifierT d3 = DiversifierT.random(); |
| 2531 | + PaymentAddress paymentAddress3 = incomingViewingKey.address(d3).get(); |
| 2532 | + byte[] memo3 = org.tron.keystore.Wallet.generateRandomBytes(512); |
| 2533 | + builder2.addOutput(expsk2.getOvk(), paymentAddress3, |
| 2534 | + (1000 * 1000000L - wallet.getShieldedTransactionFee()) / 2 - wallet |
| 2535 | + .getShieldedTransactionFee(), memo3); |
| 2536 | + |
| 2537 | + TransactionCapsule transactionCap2 = builder2.build(); |
| 2538 | + boolean ok2 = dbManager.pushTransaction(transactionCap2); |
| 2539 | + Assert.assertTrue(ok2); |
| 2540 | + } finally { |
| 2541 | + // DposTask.init() does not reset isRunning (it stays false after stop()), so force it back |
| 2542 | + // to true via reflection before restarting. |
| 2543 | + Field isRunning = DposTask.class.getDeclaredField("isRunning"); |
| 2544 | + isRunning.setAccessible(true); |
| 2545 | + isRunning.set(dposTask, true); |
| 2546 | + consensusService.start(); |
| 2547 | + } |
| 2548 | + } |
| 2549 | + |
| 2550 | + // Returns the earliest timestamp at which witnessAddr is the DPoS-scheduled producer, |
| 2551 | + // relative to the current chain head. Using this avoids relying on the genesis-only |
| 2552 | + // bypass in validBlock() (latestBlockHeaderNumber == 0) when prior tests have pushed blocks. |
| 2553 | + private long nextScheduledTime(ByteString witnessAddr) { |
| 2554 | + int size = chainBaseManager.getWitnessScheduleStore().getActiveWitnesses().size(); |
| 2555 | + for (long slot = 1; slot <= size; slot++) { |
| 2556 | + if (dposSlot.getScheduledWitness(slot).equals(witnessAddr)) { |
| 2557 | + return dposSlot.getTime(slot); |
| 2558 | + } |
2510 | 2559 | } |
2511 | | - |
2512 | | - //build output proof |
2513 | | - SpendingKey sk3 = SpendingKey.random(); |
2514 | | - FullViewingKey fvk3 = sk3.fullViewingKey(); |
2515 | | - IncomingViewingKey ivk3 = fvk3.inViewingKey(); |
2516 | | - |
2517 | | - DiversifierT d3 = DiversifierT.random(); |
2518 | | - PaymentAddress paymentAddress3 = incomingViewingKey.address(d3).get(); |
2519 | | - byte[] memo3 = org.tron.keystore.Wallet.generateRandomBytes(512); |
2520 | | - builder2.addOutput(expsk2.getOvk(), paymentAddress3, |
2521 | | - (1000 * 1000000L - wallet.getShieldedTransactionFee()) / 2 - wallet |
2522 | | - .getShieldedTransactionFee(), memo3); |
2523 | | - |
2524 | | - TransactionCapsule transactionCap2 = builder2.build(); |
2525 | | - boolean ok2 = dbManager.pushTransaction(transactionCap2); |
2526 | | - Assert.assertTrue(ok2); |
| 2560 | + throw new IllegalStateException("No scheduled slot for witness within " |
| 2561 | + + size + " slots: " + ByteArray.toHexString(witnessAddr.toByteArray())); |
2527 | 2562 | } |
2528 | 2563 |
|
2529 | 2564 | @Test |
|
0 commit comments