Skip to content

Commit

Permalink
Merge pull request #666 from doitian/custom-script-doc
Browse files Browse the repository at this point in the history
docs: document script handler and signer
  • Loading branch information
doitian committed Sep 5, 2023
2 parents d05f5e6 + 53105b3 commit 989726a
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,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 @@ -94,9 +100,24 @@ 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);
}

/**
* 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 989726a

Please sign in to comment.