Skip to content

[DISCUSSION] - BRC-100 - createAction clarification #79

Description

@dorzepowski

BRC ID

100

Discussion

I would like clarification regarding the createAction method defined in BRC-100. The questions primarily concern the "Method Calls" specification section.

  1. Request Structure
    1. The method is called "create action." Could you clarify what "action" refers to in this context? Is it effectively creating or submitting a transaction?
    2. If the only required parameter is description, what occurs if the user provides only this parameter?
    3. The documentation does not mention the use of labels. Is it allowed to include labels for customization within the wallet? For example, can labels be used as triggers for other operations when a transaction with a specific label is created?
    4. What should happen if both inputBEEF and inputs are provided?
    5. If I already have a prepared transaction and corresponding BEEF data, can I use this endpoint, or should I use a different one?
  2. Inputs Array
    1. What is the intended purpose of the inputDescription field within the input array?
    2. Why is the inputDescription field required?
    3. Since this field is part of the input object, would it be simpler to call it description instead of inputDescription?
  3. Outputs Array
    1. What happens if basket is not provided? Is there a default categorization?
    2. What is the difference between a transaction label and an output tag?
    3. Are tags allowed to influence additional customization features, such as triggering specific operations when a transaction with a given tag is created?
    4. Are there any structural limitations for tags?
  4. Options
    1. What occurs if signAndProcess is not provided?
    2. Could you explain the concept of "accept delayed broadcast," how to use it, and its intended use cases?
    3. What does "trust self" mean in this context, and how does it relate to the transaction?
    4. What is the purpose of the knownTxids parameter?
    5. What does noSendChange do, and in which scenarios would it be useful?
    6. If randomizeOutputs is set to true, should the wallet shuffle the user-provided outputs array?
  5. Response Values
    1. (Related to 4.5) Could you clarify the purpose of noSendChange?
    2. How do the statuses unproven and sending differ?
    3. How should signable transactions be used in this endpoint, given that it does not allow providing a pre-prepared BEEF structure?
    4. It seems that the signable transaction structure might need to be extensible. For example:
      1. How can a user indicate that one input requires a key with a certain security level and another requires a different level?
      2. If a new derivation scheme is introduced, would this API need updating, and how would that affect backward compatibility?
      3. If a wallet still uses an older derivation scheme (like BIP32), how can this API accommodate it so that more wallets can conform without enforcing a full migration to a new scheme?
  6. Error Handling
    1. Are there recommended validation steps that wallets should perform before processing a request, and what are best practices for handling malformed inputs?
    2. Are there specific error codes for missing or incorrect parameters?

Activity

  1. ty-everett commented on Dec 6, 2024

    @ty-everett
    Collaborator

    I will answer a few of these now, and I'll also ask my team to provide answers to the ones that I haven't covered.

    The method is called "create action." Could you clarify what "action" refers to in this context? Is it effectively creating or submitting a transaction?

    An Action is a transaction. See "Action Oriented Programming" from https://projectbabbage.com/docs/babbage-sdk/concepts/actions-aop

    Action = Bitcoin transaction.

    If the only required parameter is description, what occurs if the user provides only this parameter?

    Actions need at least one input OR one output. If there is neither, it is an error.

    The documentation does not mention the use of labels. Is it allowed to include labels for customization within the wallet? For example, can labels be used as triggers for other operations when a transaction with a specific label is created?

    Labels are for allowing a transaction to later be found using listActions. They cannot be used as triggers, they are for categorization. One transaction can have many labels.

    What should happen if both inputBEEF and inputs are provided?

    When inputs is provided, inputBEEF is required as an additional parameter. This provides the context for the input.

    If I already have a prepared transaction and corresponding BEEF data, can I use this endpoint, or should I use a different one?

    This endpoint should be used when your goal is to create a new transaction. If your goal is to let a recipient wallet know about a transaction that you've already created, then you should use internalizeAction instead.

    What is the intended purpose of the inputDescription field within the input array?

    To allow the user to know the context around when a previous token is consumed.

    Why is the inputDescription field required?
    Since this field is part of the input object, would it be simpler to call it description instead of inputDescription?

    It's required so that there's always an accounting of why a particular token was spent, updated, or consumed, for the purpose of the user's record-keeping. It's named this way primarily for historical purposes.

    What happens if basket is not provided? Is there a default categorization?

    If no basket is provided, then the wallet will not track the output at all, and it will be an untracked output (the wallet will not store information about it, and it can never appear in listOutputs results.

    What is the difference between a transaction label and an output tag?

    A transaction label is transaction-level categorization, used when retrieving or filtering a list of transactions (from listActions). Conversely, an output tag is an output-level categorization, used when retrieving or filtering a list of outputs (from listOutputs).

    Are tags allowed to influence additional customization features, such as triggering specific operations when a transaction with a given tag is created?

    We must strike transaction and replace it with output in the question, as tags are an output-level construct:

    Are tags allowed to influence additional customization features, such as triggering specific operations when a transaction output with a given tag is created?

    Output tags, like transaction labels, are a mechanism of categorization and filtering, not a triggering mechanism. They allow tagged outputs to be later retrieved based on various criterion from the wallet, using the listOutputs method.

    Are there any structural limitations for tags?

    Tags must be strings that comply with the restrictions on byte length. Beyond this, tags may be any valid string.

    Options, Response values, error handling

    Paging @tonesnotes to provide an answer on these.

    However, I will speak to the signableAction structure, and the points within 5.4, so that Tone does not have to answer that one:

    It seems that the signable transaction structure might need to be extensible. For example:

    The signable action structure is used when a user wants to redeem custom tokens, not controlled by the wallet.

    • In most cases, a transaction will be returned and not a signable action.
    • If a signable action is returned, it comprises a BEEF v2 structure with missing unlocking scripts on the inputs that are custom, and in need of signature.
    • However, in this case, all the outputs and all other inputs are already selected and provided, so that signatures and unlocking scripts can be computed using any arbitrary third-party application logic.
    • The unlocking scripts are then provided, together with the reference number, to the signAction method, which then completes the processing of the transaction.
    • To indicate which inputs are in need of having custom signatures and unlocking scripts computed, we make use of the inputs array. For each input, if its unlockingScript is provided directly, we do not need to sign it with signAction.
    • However, if instead of providing an unlocking script, we provided unlockingScriptLength estimate for that input, then the input must be flagged for later signing using signAction — application-level code will then call signAction and provide the required unlocking script.

    Because the signAction process, and the mechanisms of utilizing an unlocking script, are custom and related to the specific inputs being dealt with, which may be arbitrary in nature, the process of evaluating the provided unlocking script is not related to any key derivation process of the wallet itself — instead, it is deferred to the rules of the Bitcoin script language, interpreter, and the policies of transaction processors. The wallet does not utilize any key derivation schemes when dealing with arbitrary and custom unlocking scripts on externally-managed tokens.

    How can a user indicate that one input requires a key with a certain security level and another requires a different level?

    A user doe not indicate this to the wallet. Instead, if an input is externally-managed (an application-managed input), then:

    • If the user provides unlockingScript directly, the unlocking script is applied to the input.
    • If instead, the user provides an unlockingScriptLength estimation, then a signableAction is returned, and the signAction process must later be employed by the user in order to provide the correct unlocking script.
    • However, the mechanism utilized in order to obtain the valid unlocking script does not concern the wallet. It may or may not involve key derivation, or other wallet-related cryptographic operations or signature computations — it may be fully external, utilize sCrypt, or any other external mechanism.
    • Thus, the wallet does not deal with keys of differing security levels here, or any other such constructs. Instead, it merely applies the provided custom unlocking script to the foreign UTXO, and evaluates the spend using the script interpreter to determine its validity.

    If a new derivation scheme is introduced, would this API need updating, and how would that affect backward compatibility?

    A new key derivation scheme will not be required, and the API for transaction creation does not closely relate to key derivation. Beyond the requirement for internalizeAction to accept payment remittances through a derivation prefix and derivation suffix as described in BRC-29, the underlying mechanism of wallet operations within the createAction / signAction scheme is not related to which key derivation scheme the wallet uses.

    The only methods that are related are related to cryptographic operations, digital signatures, and identity management. For these components, the BKDS (BSV Key Derivation Scheme) is used, and it's a dependency of this specification. There is no backwards-compatibility, and no changes to the scheme are ever permitted by the specification. The key derivation scheme is foundational, and required to be fixed. Any change would break all implementations.

    If a wallet still uses an older derivation scheme (like BIP32), how can this API accommodate it so that more wallets can conform without enforcing a full migration to a new scheme?

    This specification forces compatibility with a new scheme, and forces a full migration to the new system. BIP32 is fundamentally incompatible with the primitives used for all foundational operations, including identity management and digital certificates. Use of this older scheme would open many attack vectors and privacy issues. To achieve compliance, wallets must upgrade to BKDS.

  2. tonesnotes commented on Dec 6, 2024

    @tonesnotes
    Contributor

    Options

    What occurs if signAndProcess is not provided?

    Many options are opitonal boolean values. They are typed as BooleanDefaultTrue or BooleanDefaultFalse. In this case it is default true which means by default, the new transaction will be signed and processed without signAction being required.

    Could you explain the concept of "accept delayed broadcast," how to use it, and its intended use cases?

    By default new transactions are broadcast by a background process, that is the createAction call will likely return before the transaction has been broadcast to the bitcoin network. In some cases the application is willing to wait for an initial broadcast attempt to be made in which case createAction (or signAction) doesn't return until that happens.

    What does "trust self" mean in this context, and how does it relate to the transaction?

    Setting trustSelf: 'known' allows for significantly slimmer Beefs to be sent from the wallet to the backend servers.
    When prior outputs are included as inputs in a new transaction, the server already knows they are valid. Thus the Beef sent to the server for the new transaction can omit raw transaction and proof data for these outputs.

    What is the purpose of the knownTxids parameter?

    When the wallet returns a Beef to the user, if there are transactions whose validity is already known to the application layer, they can include these txids in knownTxids to avoid redundant data being returned by the backend services or wallet.

    4.5 What does noSendChange do, and in which scenarios would it be useful?

    noSendChange is critical when building batches of transactions. To create a batch, use the noSend flag on all of the createAction calls and set sendWith to all previously created actions for the final action. noSendChain allows for effecient change management when transactions will be sent as a batch. The change from the previous noSend action starts the funding for the next noSend action.

    If randomizeOutputs is set to true, should the wallet shuffle the user-provided outputs array?

    no

    Response Values

    (Related to 4.5) Could you clarify the purpose of noSendChange?

    Forward the noSendChange response from on noSend createAction call to the next through the noSendChange option.

    How do the statuses unproven and sending differ?

    Unproven transactions are known to the bitcoin network but have not been mined into a block yet and therefore lack merkle proof data. A transaction is completed once it has merkle proof data. A transaction with status 'sending' has not yet been successfully broadcast to the bitcoin network. Typically 'sending' status doesn't last long, but due to network outages, service failures or other issues it may take time for the bitcoin network to accept the transaction.

    How should signable transactions be used in this endpoint, given that it does not allow providing a pre-prepared BEEF structure?

    The signableTransaction response allows the user to call Transaction.fromAtomicBEEF(signableTransaction) to obtain an unsigned parsed bitcoin transaction. The reason for this is to allow the user to directly control the signing of specific user provided inputs. Once this is done, the signed unlockingScripts are included in a subsequent call to signAction to complete the original createAction and process the new transaction.

    It seems that the signable transaction structure might need to be extensible. For example:

    How can a user indicate that one input requires a key with a certain security level and another requires a different level?

    The parsed unsigned Transaction can have unlockingScriptTemplates assigned to specific inputs such that when the sign() method is called the correct unlockingScript values will be computed for those inputs.

    If a new derivation scheme is introduced, would this API need updating, and how would that affect backward compatibility?

    Create a new unlockingScriptTemplate for the derivation scheme and use it.

    If a wallet still uses an older derivation scheme (like BIP32), how can this API accommodate it so that more wallets can conform without enforcing a full migration to a new scheme?

    Use a BIP32 unlockingScriptTemplate.

    Error Handling

    Are there recommended validation steps that wallets should perform before processing a request, and what are best practices for handling malformed inputs?

    This is a weak point in the current specification that we are moving to improve through the NinjaWallet proposed work.
    For invalid inputs we propose to standardize on an object with at least the following properties being thrown as an error:

    {
      isError: true,
      name: 'WERR_INVALID_PARAMETER',
      message: <a string detailing the specifc parameter and the nature of the error>
    }
    

    Are there specific error codes for missing or incorrect parameters?

    This area of the specification needs work...

  3. ty-everett commented on Dec 10, 2024

    @ty-everett
    Collaborator

    Further clarification has been added to BRC-100: #82

  4. locked and limited conversation to collaborators on Dec 15, 2024
  5. converted this issue into a discussion #85 on Dec 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions