use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class ContractServiceImpl method transfer.
/**
* @param from
* @param to
* @param values
* @param fee
* @param isSendBack
* @param orginHash
* @param blockTime
* @param toMaps
* @param contractUsedCoinMap 组装时不操作toMaps, 用 contractUsedCoinMap 来检查UTXO是否已经被使用,如果已使用则跳过
* (合约转账(从合约转出)不同于普通转账,普通转账有本地账本来维护UTXO,并且在打包前已经组装好UTXO,
* 而合约转账(从合约转出)是在打包时才组装,此时从合约账本[DB]及打包交易[toMaps]中拿到所有的utxo来组装,
* 用 contractUsedCoinMap 来代表已使用的UTXO)
* @param bestHeight
* @return
*/
private Result<ContractTransferTransaction> transfer(byte[] from, byte[] to, Na values, Na fee, boolean isSendBack, NulsDigestData orginHash, long blockTime, Map<String, Coin> toMaps, Map<String, Coin> contractUsedCoinMap, Long bestHeight) {
try {
if (!ContractLedgerUtil.isExistContractAddress(from)) {
return Result.getFailed(ContractErrorCode.CONTRACT_ADDRESS_NOT_EXIST);
}
ContractTransferTransaction tx = new ContractTransferTransaction();
tx.setTime(blockTime);
CoinData coinData = new CoinData();
List<Coin> tos = coinData.getTo();
Coin toCoin = new Coin(to, values.subtract(fee));
tos.add(toCoin);
// 加入toMaps、contractUsedCoinMap组装UTXO
// 组装时不操作toMaps, 用 contractUsedCoinMap 来检查UTXO是否已经被使用,如果已使用则跳过
CoinDataResult coinDataResult = getContractSpecialTransferCoinData(from, values, toMaps, contractUsedCoinMap, bestHeight);
if (!coinDataResult.isEnough()) {
return Result.getFailed(TransactionErrorCode.INSUFFICIENT_BALANCE);
}
coinData.setFrom(coinDataResult.getCoinList());
if (coinDataResult.getChange() != null) {
tos.add(coinDataResult.getChange());
}
tx.setCoinData(coinData);
byte successByte;
byte[] remark = null;
if (isSendBack) {
successByte = 0;
remark = ContractConstant.SEND_BACK_REMARK.getBytes(NulsConfig.DEFAULT_ENCODING);
} else {
successByte = 1;
}
tx.setRemark(remark);
tx.setTxData(new ContractTransferData(orginHash, from, successByte));
tx.setHash(NulsDigestData.calcDigestData(tx.serializeForHash()));
// 维护合约地址连续转出交易的未花费UTXO
byte[] txBytes = tx.getHash().serialize();
for (int i = 0, size = tos.size(); i < size; i++) {
if (toMaps != null) {
toMaps.put(LedgerUtil.asString(ArraysTool.concatenate(txBytes, new VarInt(i).encode())), tos.get(i));
}
}
// 合约转账(从合约转出)交易不需要签名
return Result.getSuccess().setData(tx);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class ContractServiceImpl method rollbackToMapAndContractUsedCoinMap.
private void rollbackToMapAndContractUsedCoinMap(Transaction tx, Map<String, Coin> toMaps, Map<String, Coin> contractUsedCoinMap) {
if (tx == null || tx.getCoinData() == null || contractUsedCoinMap == null) {
return;
}
CoinData coinData = tx.getCoinData();
List<Coin> froms = coinData.getFrom();
List<Coin> tos = coinData.getTo();
String key;
for (Coin from : froms) {
key = from.getKey();
if (key != null) {
contractUsedCoinMap.remove(from.getKey());
}
}
try {
byte[] txHashBytes = tx.getHash().serialize();
for (int i = 0, size = tos.size(); i < size; i++) {
toMaps.remove(LedgerUtil.asString(ArraysTool.concatenate(txHashBytes, new VarInt(i).encode())));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class ContractUtil method getStateRoot.
public static byte[] getStateRoot(BlockHeader blockHeader) {
if (blockHeader == null || blockHeader.getExtend() == null) {
return null;
}
byte[] stateRoot = blockHeader.getStateRoot();
if (stateRoot != null && stateRoot.length > 0) {
return stateRoot;
}
try {
byte[] extend = blockHeader.getExtend();
if (extend.length > BLOCK_EXTENDS_DATA_FIX_LENGTH) {
VarInt varInt = new VarInt(extend, BLOCK_EXTENDS_DATA_FIX_LENGTH);
int lengthFieldSize = varInt.getOriginalSizeInBytes();
int stateRootlength = (int) varInt.value;
stateRoot = new byte[stateRootlength];
System.arraycopy(extend, BLOCK_EXTENDS_DATA_FIX_LENGTH + lengthFieldSize, stateRoot, 0, stateRootlength);
blockHeader.setStateRoot(stateRoot);
return stateRoot;
}
} catch (Exception e) {
Log.error("parse stateRoot error.", e);
}
return null;
}
use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class UtxoLedgerServiceImpl method rollbackUnlockTxCoinData.
@Override
public Result rollbackUnlockTxCoinData(Transaction tx) throws NulsException {
if (tx == null || tx.getCoinData() == null) {
return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.NULL_PARAMETER);
}
try {
CoinData coinData = tx.getCoinData();
List<Coin> tos = coinData.getTo();
boolean isExistLockUtxo = false;
Coin needUnLockUtxo = null;
int needUnLockUtxoIndex = 0;
for (Coin to : tos) {
if (to.getLockTime() == -1) {
isExistLockUtxo = true;
needUnLockUtxo = to;
break;
}
needUnLockUtxoIndex++;
}
if (!isExistLockUtxo) {
return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.UTXO_STATUS_CHANGE);
}
byte[] txHashBytes = tx.getHash().serialize();
Result result = utxoLedgerUtxoStorageService.saveUtxo(Arrays.concatenate(txHashBytes, new VarInt(needUnLockUtxoIndex).encode()), needUnLockUtxo);
if (result.isFailed()) {
throw new NulsException(result.getErrorCode());
}
return result;
} catch (IOException e) {
Log.error(e);
throw new NulsException(KernelErrorCode.IO_ERROR);
}
}
use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class UtxoLedgerServiceImpl method rollbackCoinData.
private Result rollbackCoinData(Transaction tx) throws IOException, NulsException {
byte[] txHashBytes = tx.getHash().serialize();
BatchOperation batch = utxoLedgerUtxoStorageService.createWriteBatch();
CoinData coinData = tx.getCoinData();
if (coinData != null) {
// 保存utxo已花费 - from
List<Coin> froms = coinData.getFrom();
Coin recovery;
for (Coin from : froms) {
try {
NulsByteBuffer byteBuffer = new NulsByteBuffer(from.getOwner());
NulsDigestData fromTxHash = byteBuffer.readHash();
int fromIndex = (int) byteBuffer.readVarInt();
Transaction fromTx = utxoLedgerTransactionStorageService.getTx(fromTxHash);
recovery = fromTx.getCoinData().getTo().get(fromIndex);
recovery.setFrom(from.getFrom());
batch.put(from.getOwner(), recovery.serialize());
} catch (IOException e) {
Log.error(e);
return Result.getFailed(KernelErrorCode.IO_ERROR);
}
}
// 删除utxo - to
List<Coin> tos = coinData.getTo();
for (int i = 0, length = tos.size(); i < length; i++) {
byte[] owner = Arrays.concatenate(txHashBytes, new VarInt(i).encode());
// Log.info("批量删除:" + Hex.encode(owner));
batch.delete(owner);
}
// 执行批量
Result batchResult = batch.executeBatch();
if (batchResult.isFailed()) {
return batchResult;
}
}
return Result.getSuccess();
}
Aggregations