Skip to content

Commit

Permalink
Merge branch 'master' into exec/develop-merge-master
Browse files Browse the repository at this point in the history
  • Loading branch information
eval-exec committed Nov 26, 2024
2 parents 615bf0e + 989726a commit b29e57a
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 3 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ Here is an example to build a CKB transfer transaction with the help of transact
String sender = "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq2qf8keemy2p5uu0g0gn8cd4ju23s5269qk8rg4r";
String receiver = "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqg958atl2zdh8jn3ch8lc72nt0cf864ecqdxm9zf";
Iterator<TransactionInput> iterator = new InputIterator(sender);
TransactionWithScriptGroups txWithGroups = new CkbTransactionBuilder(iterator, Network.TESTNET)
TransactionBuilderConfiguration configuration = new TransactionBuilderConfiguration(Network.TESTNET);
configuration.setFeeRate(1000);
TransactionWithScriptGroups txWithGroups = new CkbTransactionBuilder(configuration, iterator)
.addOutput(receiver, 50100000000L)
.setFeeRate(1000)
.setChangeOutput(sender)
.build();
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ public abstract class AbstractTransactionBuilder {
protected List<TransactionInput> inputsDetail = new ArrayList<>();
protected Transaction tx = new Transaction();

/**
* Initialites the transaction builder.
*
* @param configuration This is the bundle of configuration for builder,
* such as fee rate and registerred {@link org.nervos.ckb.transaction.handler.ScriptHandler}.
*/
public AbstractTransactionBuilder(TransactionBuilderConfiguration configuration, Iterator<TransactionInput> availableInputs) {
this.configuration = configuration;
this.availableInputs = availableInputs;
Expand Down Expand Up @@ -88,6 +94,14 @@ protected static long calculateTxFee(Transaction transaction, long feeRate) {
return Calculator.calculateTransactionFee(transaction, feeRate);
}

/**
* Builds the transaction with a default context for script handlers.
*
* This function will call script handlers in {@code TransactionConfiguration} with a
* default context null. Use {@link #build(Object...)} to pass custom contexts.
*
* @see org.nervos.ckb.transaction.handler.ScriptHandler#buildTransaction(AbstractTransactionBuilder, ScriptGroup, Object)
*/
public TransactionWithScriptGroups build() {
return build((Object) null);
}
Expand Down Expand Up @@ -129,5 +143,12 @@ public Map<Script, ScriptGroup> rebuildScriptGroups(Map<Script, ScriptGroup> scr
}
return ret;
}
/**
* Builds the transaction with custom contexts for script handlers.
*
* The contexts will be passed to the registered script handlers in the same order.
*
* @see org.nervos.ckb.transaction.handler.ScriptHandler#buildTransaction(AbstractTransactionBuilder, ScriptGroup, Object)
*/
abstract TransactionWithScriptGroups build(Object... contexts);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,58 @@
import org.nervos.ckb.sign.ScriptGroup;
import org.nervos.ckb.transaction.AbstractTransactionBuilder;

/**
* ScriptHandler implements the building logic for various scripts.
*
* These handlers should be registered in the transaction builder via {@link
* org.nervos.ckb.transaction.TransactionBuilderConfiguration}.
*/
public interface ScriptHandler {
/**
* Build the transaction for the script.
*
* This function is called by transaction builder for each script group and each context.
*
* Generally this function should:
*
* <ol>
* <li>Check the scriptGroup to determine whether to proceed with the next steps or skip them.</li>
* <li>Add cell deps for the script.</li>
* <li>
* Prefill the witness for the script so the transaction size will not
* increase after signing, which may invalidate the fee calculation.
* </li>
* </ol>
*
* <p>For example:</p>
*
* <pre>{@code
* @Override
* boolean buildTransaction(AbstractTransactionBuilder txBuilder, ScriptGroup scriptGroup, Object context) {
* // Only change the transaction when the script is used.
* if (scriptGroup == null || !isMatched(scriptGroup.getScript())) {
* return false;
* }
* // Add celldeps
* txBuilder.addCellDeps(cellDeps);
*
* // Prefill witness placeholder
* int witnessIndex = scriptGroup.getInputIndices().get(0);
* byte[] dummyWitness = new byte[8];
* txBuilder.setWitness(witnessIndex, WitnessArgs.Type.LOCK, dummyWitness);
*
* return true;
* }
* }</pre>
*
* @param txBuilder The transaction in building.
* @param scriptGroup Transaction builder calls this callback for each script group found in the transaction.
* The script handler is responsoble for determining whether it should handle the given script group.
* @param context This is null passed from {@link org.nervos.ckb.transaction.AbstractTransactionBuilder#build()},
* or provided contexts in {@link org.nervos.ckb.transaction.AbstractTransactionBuilder#build(Object...)}.
* @return {@code true} when the script handler has modified the transaction.
*
*/
boolean buildTransaction(AbstractTransactionBuilder txBuilder, ScriptGroup scriptGroup, Object context);

void init(Network network);
Expand Down
21 changes: 21 additions & 0 deletions core/src/main/java/org/nervos/ckb/sign/ScriptSigner.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

import org.nervos.ckb.type.Transaction;

/**
* ScriptSigner implements the signing logic for various scripts.
*
* These signers should be registered in {@link TransactionSigner}.
*/
public interface ScriptSigner {
/**
* Sign the transaction for the script.
*
* This function is called by {@link TransactionSigner}
* for each context and each matched script group.
*
* @param transaction The transaction to be signed.
* @param scriptGroup TransactionSigner selects the corresponding ScriptSigner for each script group.
* This selection is based on the registered ScriptSigner's provided script type and hash.
* @param context This is passed from {@code TransactionSigner.signTransaction}
* @return {@code true} when the script handler has modified the transaction.
*
* @see TransactionSigner#signTransaction(TransactionWithScriptGroups, Context...)
* @see TransactionSigner#signTransaction(TransactionWithScriptGroups, Set<Context>)
* @see TransactionSigner#signTransaction(TransactionWithScriptGroups, String...)
*/
boolean signTransaction(Transaction transaction, ScriptGroup scriptGroup, Context context);
}
22 changes: 21 additions & 1 deletion core/src/main/java/org/nervos/ckb/sign/TransactionSigner.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,25 @@ public TransactionSigner registerLockScriptSigner(String codeHash, ScriptSigner
return registerLockScriptSigner(Numeric.hexStringToByteArray(codeHash), scriptSigner);
}


/**
* signTransaction signs the transaction using registered ScriptSigners.
*
* @param transaction Transaction to be signed.
* @param contexts Contexts for {@link org.nervos.ckb.sign.ScriptSigner}.
* @return signed groups indices.
*/
public Set<Integer> signTransaction(
TransactionWithScriptGroups transaction, Context... contexts) {
return signTransaction(transaction, new HashSet<>(Arrays.asList(contexts)));
}

/**
* signTransaction signs the transaction using registered ScriptSigners.
*
* @param transaction Transaction to be signed.
* @param contexts Contexts for {@link org.nervos.ckb.sign.ScriptSigner}.
* @return signed groups indices.
*/
public Set<Integer> signTransaction(
TransactionWithScriptGroups transaction, Set<Context> contexts) {
Set<Integer> signedGroupsIndices = new HashSet<>();
Expand Down Expand Up @@ -122,6 +135,13 @@ public Set<Integer> signTransaction(
return signedGroupsIndices;
}

/**
* signTransaction signs the transaction using registered ScriptSigners.
*
* @param transaction Transaction to be signed.
* @param privateKeys Each private key is wrapped in one {@link Context}. These contexts will be passed to ScriptSigners.
* @return signed groups indices.
*/
public Set<Integer> signTransaction(
TransactionWithScriptGroups transaction, String... privateKeys) {
Contexts contexts = new Contexts();
Expand Down

0 comments on commit b29e57a

Please sign in to comment.