Browse Source

在transactonContent对象中添加txOpTime字段,避免重复执行合约时,出现contentHash碰撞的问题。

tags/1.0.0
zhaoguangwei 6 years ago
parent
commit
a64ab90dd9
6 changed files with 264 additions and 239 deletions
  1. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java
  2. +25
    -21
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java
  3. +44
    -36
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java
  4. +89
    -88
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java
  5. +104
    -92
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java
  6. +1
    -1
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java

+ 1
- 1
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java View File

@@ -42,7 +42,7 @@ public class ContractEventSendOperationHandle implements OperationHandle {
contract.getAddress().toBase58(),contract.getChaincodeVersion(),contract.getChainCode()). contract.getAddress().toBase58(),contract.getChaincodeVersion(),contract.getChainCode()).
processEvent(localContractEventContext); processEvent(localContractEventContext);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
throw new LedgerException("contract processEvent exception. detail:"+e.getMessage());
} }
} }




+ 25
- 21
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java View File

@@ -1,21 +1,25 @@
package com.jd.blockchain.ledger;
import com.jd.blockchain.base.data.TypeCodes;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.utils.ValueType;
/**
* 交易内容;
*
* @author huanghaiquan
*
*/
@DataContract(code= TypeCodes.TX_CONTENT)
public interface TransactionContent extends TransactionContentBody, HashObject {
@Override
@DataField(order=1, primitiveType = ValueType.BYTES)
HashDigest getHash();
}
package com.jd.blockchain.ledger;

import com.jd.blockchain.base.data.TypeCodes;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.utils.ValueType;

/**
* 交易内容;
*
* @author huanghaiquan
*
*/
@DataContract(code= TypeCodes.TX_CONTENT)
public interface TransactionContent extends TransactionContentBody, HashObject {
@Override
@DataField(order=1, primitiveType = ValueType.BYTES)
HashDigest getHash();

//获得交易操作时间;
@DataField(order=2, primitiveType = ValueType.INT64)
Long getTxOpTime();

}

+ 44
- 36
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java View File

@@ -1,36 +1,44 @@
package com.jd.blockchain.ledger;
import com.jd.blockchain.base.data.TypeCodes;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.utils.ValueType;
/**
* 交易内容;
*
* @author huanghaiquan
*
*/
@DataContract(code = TypeCodes.TX_CONTENT_BODY)
public interface TransactionContentBody {
/**
* 执行交易的账本地址;
*
* 注:除了账本的创世交易之外,任何交易的账本地址都不允许为 null;
*
* @return
*/
@DataField(order = 1, primitiveType = ValueType.BYTES)
HashDigest getLedgerHash();
/**
* 操作列表;
*
* @return
*/
@DataField(order = 2, list = true, refContract = true, genericContract = true)
Operation[] getOperations();
}
package com.jd.blockchain.ledger;

import com.jd.blockchain.base.data.TypeCodes;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.utils.ValueType;

/**
* 交易内容;
*
* @author huanghaiquan
*
*/
@DataContract(code = TypeCodes.TX_CONTENT_BODY)
public interface TransactionContentBody {

/**
* 执行交易的账本地址;
*
* 注:除了账本的创世交易之外,任何交易的账本地址都不允许为 null;
*
* @return
*/
@DataField(order = 1, primitiveType = ValueType.BYTES)
HashDigest getLedgerHash();

/**
* 操作列表;
*
* @return
*/
@DataField(order = 2, list = true, refContract = true, genericContract = true)
Operation[] getOperations();

/**
* 交易操作时间
*
* @return
*/
@DataField(order = 3, primitiveType = ValueType.INT64)
Long getTxOpTime();

}

+ 89
- 88
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java View File

@@ -1,88 +1,89 @@
package com.jd.blockchain.ledger.data;
import com.jd.blockchain.binaryproto.BinaryEncodingUtils;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoUtils;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.ledger.TransactionBuilder;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.utils.Bytes;
public class TxBuilder implements TransactionBuilder {
static {
DataContractRegistry.register(TransactionContentBody.class);
}
private BlockchainOperationFactory opFactory = new BlockchainOperationFactory();
private CryptoAlgorithm defaultHashAlgorithm = CryptoAlgorithm.SHA256;
private HashDigest ledgerHash;
public TxBuilder(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}
@Override
public TransactionRequestBuilder prepareRequest() {
TransactionContent txContent = prepareContent();
return new TxRequestBuilder(txContent);
}
@Override
public TransactionContent prepareContent() {
TxContentBlob txContent = new TxContentBlob(ledgerHash);
txContent.addOperations(opFactory.getOperations());
byte[] contentBodyBytes = BinaryEncodingUtils.encode(txContent, TransactionContentBody.class);
HashDigest contentHash = CryptoUtils.hash(defaultHashAlgorithm).hash(contentBodyBytes);
txContent.setHash(contentHash);
return txContent;
}
@Override
public LedgerInitOperationBuilder ledgers() {
return opFactory.ledgers();
}
@Override
public UserRegisterOperationBuilder users() {
return opFactory.users();
}
@Override
public DataAccountRegisterOperationBuilder dataAccounts() {
return opFactory.dataAccounts();
}
@Override
public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) {
return opFactory.dataAccount(accountAddress);
}
@Override
public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) {
return opFactory.dataAccount(accountAddress);
}
@Override
public ContractCodeDeployOperationBuilder contracts() {
return opFactory.contracts();
}
@Override
public ContractEventSendOperationBuilder contractEvents() {
return opFactory.contractEvents();
}
}
package com.jd.blockchain.ledger.data;

import com.jd.blockchain.binaryproto.BinaryEncodingUtils;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoUtils;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.ledger.TransactionBuilder;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.utils.Bytes;

public class TxBuilder implements TransactionBuilder {

static {
DataContractRegistry.register(TransactionContentBody.class);
}

private BlockchainOperationFactory opFactory = new BlockchainOperationFactory();

private CryptoAlgorithm defaultHashAlgorithm = CryptoAlgorithm.SHA256;

private HashDigest ledgerHash;

public TxBuilder(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}

@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}

@Override
public TransactionRequestBuilder prepareRequest() {
TransactionContent txContent = prepareContent();
return new TxRequestBuilder(txContent);
}
@Override
public TransactionContent prepareContent() {
TxContentBlob txContent = new TxContentBlob(ledgerHash);
txContent.addOperations(opFactory.getOperations());
txContent.setTxOpTime(System.currentTimeMillis());
byte[] contentBodyBytes = BinaryEncodingUtils.encode(txContent, TransactionContentBody.class);
HashDigest contentHash = CryptoUtils.hash(defaultHashAlgorithm).hash(contentBodyBytes);
txContent.setHash(contentHash);
return txContent;
}

@Override
public LedgerInitOperationBuilder ledgers() {
return opFactory.ledgers();
}
@Override
public UserRegisterOperationBuilder users() {
return opFactory.users();
}

@Override
public DataAccountRegisterOperationBuilder dataAccounts() {
return opFactory.dataAccounts();
}
@Override
public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) {
return opFactory.dataAccount(accountAddress);
}

@Override
public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) {
return opFactory.dataAccount(accountAddress);
}

@Override
public ContractCodeDeployOperationBuilder contracts() {
return opFactory.contracts();
}

@Override
public ContractEventSendOperationBuilder contractEvents() {
return opFactory.contractEvents();
}

}

+ 104
- 92
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java View File

@@ -1,92 +1,104 @@
package com.jd.blockchain.ledger.data;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.jd.blockchain.binaryproto.DConstructor;
import com.jd.blockchain.binaryproto.FieldSetter;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.utils.io.NumberMask;
/**
* 交易内容的数据块;
* <p>
*
* 包含原始交易请求的数据块;
*
* @author huanghaiquan
*
*/
public class TxContentBlob implements TransactionContent {
/**
* 操作数量的最大值;
*/
public static final int MAX_OP_COUNT = NumberMask.SHORT.MAX_BOUNDARY_SIZE;
private List<Operation> operationList = new ArrayList<Operation>();
private HashDigest hash;
private HashDigest ledgerHash;
@DConstructor(name ="TxContentBlob")
public TxContentBlob(@FieldSetter(name="getLedgerHash", type="HashDigest") HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
/**
* 交易内容的哈希值;
*/
@Override
public HashDigest getHash() {
return this.hash;
}
/**
* 更新交易内容的哈希值;
* <p>
* 注:当前对象只充当值对象,不校验指定哈希值的完整性,调用者应该在外部实施完整性校验;
* @param hash
*/
public void setHash(HashDigest hash) {
this.hash = hash;
}
/**
* 交易请求链的hash
*
* @return
*/
@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}
public void setLedgerHash(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}
@Override
public Operation[] getOperations() {
return operationList.toArray(new Operation[operationList.size()]);
}
public void setOperations(Object[] operations) {
//in array's case ,cast will failed!
for (Object operation : operations) {
Operation op = (Operation)operation;
addOperation(op);
}
}
public void addOperation(Operation operation) {
operationList.add(operation);
}
public void addOperations(Collection<Operation> operations) {
operationList.addAll(operations);
}
}
package com.jd.blockchain.ledger.data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.jd.blockchain.binaryproto.DConstructor;
import com.jd.blockchain.binaryproto.FieldSetter;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.utils.io.NumberMask;

/**
* 交易内容的数据块;
* <p>
*
* 包含原始交易请求的数据块;
*
* @author huanghaiquan
*
*/
public class TxContentBlob implements TransactionContent {

/**
* 操作数量的最大值;
*/
public static final int MAX_OP_COUNT = NumberMask.SHORT.MAX_BOUNDARY_SIZE;

private List<Operation> operationList = new ArrayList<Operation>();

private HashDigest hash;

private HashDigest ledgerHash;

//交易操作时间;
private Long txOpTime;

@DConstructor(name ="TxContentBlob")
public TxContentBlob(@FieldSetter(name="getLedgerHash", type="HashDigest") HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}

/**
* 交易内容的哈希值;
*/
@Override
public HashDigest getHash() {
return this.hash;
}
/**
* 更新交易内容的哈希值;
* <p>
* 注:当前对象只充当值对象,不校验指定哈希值的完整性,调用者应该在外部实施完整性校验;
* @param hash
*/
public void setHash(HashDigest hash) {
this.hash = hash;
}

/**
* 交易请求链的hash
*
* @return
*/
@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}
public void setLedgerHash(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
}

@Override
public Operation[] getOperations() {
return operationList.toArray(new Operation[operationList.size()]);
}

public void setOperations(Object[] operations) {
//in array's case ,cast will failed!
for (Object operation : operations) {
Operation op = (Operation)operation;
addOperation(op);
}
}

public void addOperation(Operation operation) {
operationList.add(operation);
}
public void addOperations(Collection<Operation> operations) {
operationList.addAll(operations);
}

@Override
public Long getTxOpTime() {
return txOpTime;
}

public void setTxOpTime(Long txOpTime) {
this.txOpTime = txOpTime;
}
}

+ 1
- 1
source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java View File

@@ -139,7 +139,7 @@ public class IntegrationTest4Bftsmart {
} }


try { try {
Thread.sleep(60000);
Thread.sleep(60000000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }


Loading…
Cancel
Save