Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: document script handler and signer #666

Merged
merged 2 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading