@@ -42,7 +42,7 @@ public class ContractEventSendOperationHandle implements OperationHandle { | |||
contract.getAddress().toBase58(),contract.getChaincodeVersion(),contract.getChainCode()). | |||
processEvent(localContractEventContext); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
throw new LedgerException("contract processEvent exception. detail:"+e.getMessage()); | |||
} | |||
} | |||
@@ -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(); | |||
} |
@@ -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(); | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -139,7 +139,7 @@ public class IntegrationTest4Bftsmart { | |||
} | |||
try { | |||
Thread.sleep(60000); | |||
Thread.sleep(60000000); | |||
} catch (InterruptedException e) { | |||
e.printStackTrace(); | |||
} | |||