|
| 1 | +package io.nuls.consensus.tx.v1; |
| 2 | + |
| 3 | +import io.nuls.base.data.*; |
| 4 | +import io.nuls.base.protocol.TransactionProcessor; |
| 5 | +import io.nuls.common.ConfigBean; |
| 6 | +import io.nuls.consensus.constant.ConsensusErrorCode; |
| 7 | +import io.nuls.consensus.model.bo.Chain; |
| 8 | +import io.nuls.consensus.utils.LoggerUtil; |
| 9 | +import io.nuls.consensus.utils.manager.ChainManager; |
| 10 | +import io.nuls.core.basic.Result; |
| 11 | +import io.nuls.core.constant.TxType; |
| 12 | +import io.nuls.core.core.annotation.Autowired; |
| 13 | +import io.nuls.core.core.annotation.Component; |
| 14 | +import io.nuls.core.exception.NulsException; |
| 15 | +import io.nuls.core.model.ArraysTool; |
| 16 | +import io.nuls.transaction.model.po.TransactionConfirmedPO; |
| 17 | +import io.nuls.transaction.service.ConfirmedTxService; |
| 18 | + |
| 19 | +import java.math.BigInteger; |
| 20 | +import java.util.*; |
| 21 | + |
| 22 | +import static io.nuls.consensus.constant.ConsensusConstant.CONSENSUS_LOCK_TIME; |
| 23 | + |
| 24 | +/** |
| 25 | + * quitstakingTransaction processor |
| 26 | + * |
| 27 | + * @author tag |
| 28 | + * @date 2019/6/1 |
| 29 | + */ |
| 30 | +@Component("UnlockTransferProcessorV1") |
| 31 | +public class UnlockTransferProcessor implements TransactionProcessor { |
| 32 | + @Autowired |
| 33 | + private ChainManager chainManager; |
| 34 | + |
| 35 | + @Autowired |
| 36 | + private ConfirmedTxService txService; |
| 37 | + |
| 38 | + @Override |
| 39 | + public int getType() { |
| 40 | + return TxType.UNLOCK_TRANSFER; |
| 41 | + } |
| 42 | + |
| 43 | + @Override |
| 44 | + public Map<String, Object> validate(int chainId, List<Transaction> txs, Map<Integer, List<Transaction>> txMap, BlockHeader blockHeader) { |
| 45 | + Chain chain = chainManager.getChainMap().get(chainId); |
| 46 | + Map<String, Object> result = new HashMap<>(2); |
| 47 | + if (chain == null) { |
| 48 | + LoggerUtil.commonLog.error("Chains do not exist."); |
| 49 | + result.put("txList", txs); |
| 50 | + result.put("errorCode", ConsensusErrorCode.CHAIN_NOT_EXIST.getCode()); |
| 51 | + return result; |
| 52 | + } |
| 53 | + List<Transaction> invalidTxList = new ArrayList<>(); |
| 54 | + String errorCode = null; |
| 55 | + Set<NulsHash> hashSet = new HashSet<>(); |
| 56 | + Result rs; |
| 57 | + for (Transaction unlockTx : txs) { |
| 58 | + try { |
| 59 | + NulsHash lockHash = new NulsHash(unlockTx.getTxData()); |
| 60 | + if (null == lockHash) { |
| 61 | + invalidTxList.add(unlockTx); |
| 62 | + chain.getLogger().error("Unlock tx data is wrong:{}", unlockTx.getHash().toHex()); |
| 63 | + errorCode = ConsensusErrorCode.UNLOCK_TX_NOT_FOUND.getCode(); |
| 64 | + continue; |
| 65 | + } |
| 66 | + io.nuls.transaction.model.bo.Chain txChain = new io.nuls.transaction.model.bo.Chain(); |
| 67 | + txChain.setConfig(new ConfigBean()); |
| 68 | + txChain.getConfig().setChainId(chain.getChainId()); |
| 69 | + TransactionConfirmedPO txPo = this.txService.getConfirmedTransaction(txChain, lockHash); |
| 70 | + if (null == txPo || null == txPo.getTx() || TxType.TRANSFER != txPo.getTx().getType()) { |
| 71 | + invalidTxList.add(unlockTx); |
| 72 | + chain.getLogger().error("Unlock tx not found:{}", lockHash.toHex()); |
| 73 | + errorCode = ConsensusErrorCode.LOCKED_TX_NOT_FOUND.getCode(); |
| 74 | + continue; |
| 75 | + } |
| 76 | + |
| 77 | + CoinData lockCoinData = txPo.getTx().getCoinDataInstance(); |
| 78 | + if (null == lockCoinData || lockCoinData.getTo() == null || lockCoinData.getTo().size() != 1) { |
| 79 | + invalidTxList.add(unlockTx); |
| 80 | + chain.getLogger().error("Unlock tx coin data is null:{}", lockHash.toHex()); |
| 81 | + errorCode = ConsensusErrorCode.LOCKED_TX_NOT_FOUND.getCode(); |
| 82 | + continue; |
| 83 | + } |
| 84 | + CoinTo lockTo = lockCoinData.getTo().get(0); |
| 85 | + if (null == lockTo || lockTo.getLockTime() != CONSENSUS_LOCK_TIME) { |
| 86 | + invalidTxList.add(unlockTx); |
| 87 | + chain.getLogger().error("Unlock tx coin data is null:{}", lockHash.toHex()); |
| 88 | + errorCode = ConsensusErrorCode.LOCKED_TX_NOT_FOUND.getCode(); |
| 89 | + continue; |
| 90 | + } |
| 91 | + int lockedAssetChainId = lockTo.getAssetsChainId(); |
| 92 | + int lockedAssetId = lockTo.getAssetsId(); |
| 93 | + BigInteger lockedAmount = lockTo.getAmount(); |
| 94 | + byte[] lockedAddress = lockTo.getAddress(); |
| 95 | + |
| 96 | + CoinData coinData = unlockTx.getCoinDataInstance(); |
| 97 | + if (null == coinData || null == coinData.getTo() || null == coinData.getFrom() || coinData.getFrom().size() != 1 || coinData.getTo().size() != 1) { |
| 98 | + invalidTxList.add(unlockTx); |
| 99 | + chain.getLogger().error("Unlock tx coin data is wrong:{}", unlockTx.getHash().toHex()); |
| 100 | + errorCode = ConsensusErrorCode.UNLOCK_TX_NOT_FOUND.getCode(); |
| 101 | + continue; |
| 102 | + } |
| 103 | + |
| 104 | + CoinFrom from = coinData.getFrom().get(0); |
| 105 | + if (null == from || from.getAssetsChainId() != lockedAssetChainId || from.getAssetsId() != lockedAssetId || from.getAmount().compareTo(lockedAmount) != 0 || from.getLocked() != CONSENSUS_LOCK_TIME || !ArraysTool.arrayEquals(lockedAddress, from.getAddress())) { |
| 106 | + invalidTxList.add(unlockTx); |
| 107 | + chain.getLogger().error("Unlock tx coin data is wrong:{}", unlockTx.getHash().toHex()); |
| 108 | + errorCode = ConsensusErrorCode.UNLOCK_TX_NOT_FOUND.getCode(); |
| 109 | + continue; |
| 110 | + } |
| 111 | + |
| 112 | + CoinTo to = coinData.getTo().get(0); |
| 113 | + if (null == to || to.getAssetsChainId() != lockedAssetChainId || to.getAssetsId() != lockedAssetId || to.getAmount().compareTo(lockedAmount) != 0 || to.getLockTime() != 0 || !ArraysTool.arrayEquals(lockedAddress, to.getAddress())) { |
| 114 | + invalidTxList.add(unlockTx); |
| 115 | + chain.getLogger().error("Unlock tx coin data is wrong:{}", unlockTx.getHash().toHex()); |
| 116 | + errorCode = ConsensusErrorCode.UNLOCK_TX_NOT_FOUND.getCode(); |
| 117 | + continue; |
| 118 | + } |
| 119 | + |
| 120 | + /* |
| 121 | + * Repeated exit node |
| 122 | + * */ |
| 123 | + if (!hashSet.add(lockHash)) { |
| 124 | + invalidTxList.add(unlockTx); |
| 125 | + chain.getLogger().info("Repeated transactions"); |
| 126 | + errorCode = ConsensusErrorCode.CONFLICT_ERROR.getCode(); |
| 127 | + } |
| 128 | + } catch (NulsException e) { |
| 129 | + invalidTxList.add(unlockTx); |
| 130 | + chain.getLogger().error("Conflict calibration error"); |
| 131 | + chain.getLogger().error(e); |
| 132 | + errorCode = e.getErrorCode().getCode(); |
| 133 | + } |
| 134 | + } |
| 135 | + result.put("txList", invalidTxList); |
| 136 | + result.put("errorCode", errorCode); |
| 137 | + return result; |
| 138 | + } |
| 139 | + |
| 140 | + @Override |
| 141 | + public boolean commit(int chainId, List<Transaction> txs, BlockHeader blockHeader, int syncStatus) { |
| 142 | + return true; |
| 143 | + } |
| 144 | + |
| 145 | + @Override |
| 146 | + public boolean rollback(int chainId, List<Transaction> txs, BlockHeader blockHeader) { |
| 147 | + return true; |
| 148 | + } |
| 149 | + |
| 150 | +} |
0 commit comments