Skip to content

MISSING REQ SIGNER Fraud proof#229

Open
elRaulito wants to merge 8 commits into
mainfrom
fp-missing-req-signer
Open

MISSING REQ SIGNER Fraud proof#229
elRaulito wants to merge 8 commits into
mainfrom
fp-missing-req-signer

Conversation

@elRaulito

Copy link
Copy Markdown
Collaborator

No description provided.

@GeorgeFlerovsky GeorgeFlerovsky left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment


expect list.has(builtin.un_list_data(bad_spend_inputs), bad_input)

expect invalid_input: Input = bad_input

@GeorgeFlerovsky GeorgeFlerovsky Apr 16, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work because the transaction's spend inputs is a list of output references [OutputReference].

We have to do the lookup for the utxo output manually for this output reference, which means that we should have two different fraud proof procedures:

  1. The output reference is for a utxo produced by another transaction (t_2) in this block (MISSING-REQ-SIGNER-TX).
  2. The output reference is for a utxo (i.e. member of prev_utxos_root) that existed before this block (MISSING-REQ-SIGNER-UTXO).

I updated the spec to describe these fraud proofs. Please adapt the code accordingly.

I suggest that you implement both fraud proofs in this PR (they're quite similar).

@elRaulito

Copy link
Copy Markdown
Collaborator Author

@GeorgeFlerovsky updated the FP splitted in 2

@GeorgeFlerovsky GeorgeFlerovsky left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code doesn't compile. See comments explaining why and how to fix it

bad_spend_inputs: Data,
bad_input: Data,
parent_outputs_data: Data,
parent_outputs: List<Output>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't use the Output type inside a redeemer because Output contains a Value, which is an opaque type. This is the compilation error I got when trying to build this:

image

Instead, the parent_outputs field should be Data, from which you can select the correct output and then parse it as an Output. For example, this is how we did it in the non-existent-input fraud proof validator:

Continue {
  ...
  bad_input, // : Data
  bad_spend_inputs, // : Data
} -> {
          // Membership of the bad_input among the tx1 spent inputs
        verify_hash_32(bad_tx, bad_tx_hash)
        verify_hash_32(bad_tx_body, bad_tx.body)
        verify_hash_32(bad_spend_inputs, bad_tx_body.spend_inputs)

        expect list.has(builtin.un_list_data(bad_spend_inputs), bad_input)

        expect invalid_input: Input = bad_input
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't cast as we did because it does not allow me to cast from Data to Output since output contains Value, so it's opaque

expect bad_output: Output = real_output
     ·                                     ─────┬─────
     ·                                          ╰── reckless opaque cast
 126 │         expect invalid_input.output_reference.transaction_id == parent_tx_hash
 127 │         expect invalid_input.output == bad_output
     ╰────
  help: This expression is trying to convert something unknown into an opaque type. An opaque type is a data-type which hides its internal details; usually        
        because it enforces some specific invariant on its internal structure. For example, you might define a Natural type that holds an Integer but ensures      
        that it never gets negative.

        A direct consequence means that it isn't generally possible, nor safe, to turn *any* value into an opaque type. Instead, use the constructors and
        methods provided for lifting values into that opaque type while ensuring that any structural invariant is checked for.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elRaulito for the withdrawal contract I've used unconstr_fields to extract Output fields. Here:

// Unsafely destructuring `l2_output_data`, assuming it is structured as
// an `Output`. Since further down we are validating the presence of
// this UTxO in the latest ledger, we don't need to worry about the
// correctness of its structure here.
expect [l2_output_address_data,
l2_output_value_data, ..] = builtin.unconstr_fields(l2_output_data)

For Value, we have ValuePairs, which we can cast Data values to unsafely (which should be fine in most cases in Midgard):

// Coerce the second data under `l2_output_data` into a `ValuePairs`.
// `Value` is not allowed as its an opaque type.
expect l2_output_value: ValuePairs = l2_output_value_data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants