Skip to main content
deleted 4 characters in body
Source Link
aurexav
  • 11.2k
  • 6
  • 33

We're trying to understand the signed transaction vs. unsigned transaction lifecycle, and what ensure_signed actually does for you.

What it seemed was, if you submitted an unsigned transaction to our pallet that it would put the failed txn in the block because it should fail ensure_signed with BadOrigin, correct? Just like any other failure inside of an extrinsic. IF you assume this, then it's fine for Pays::Yes txns.

However in Pays::No txns, one would think submitting unsigned txns would be an attack vector. Yet running our chain locally, we can submit unsigned txns all day long, and they will never be put in a block as a failed transaction, it will be invalid, because it reaches, (we think) this generated/macro code in validate_unsigned, displaying UnknownTransaction::NoUnsignedValidator in the Polkadot dashboard, without our having to do anything extra.

And in fact if we call this extrinsic using Sudo, it fails with BadOrigin, and the failed transaction is included in a block...so I guess we shouldn't DoS ourselves.

So next, SignedExtension's default validate_unsigned has something very different:

    fn validate_unsigned(
        _call: &Self::Call,
        _info: &DispatchInfoOf<Self::Call>,
        _len: usize,
    ) -> TransactionValidity {
        Ok(ValidTransaction::default())
    }
fn validate_unsigned(
    _call: &Self::Call,
    _info: &DispatchInfoOf<Self::Call>,
    _len: usize,
) -> TransactionValidity {
    Ok(ValidTransaction::default())
}

Basically it seems that unsigned transactions are not calling the above default implementation, but instead the first one which is automagically generated for pallets regardless of whether they have a SignedExtension implemented. Following the code, this expand_outer_validate_unsigned function is called (probably self-evident by now) in construct_runtime.

Question is what is the use of the default for the trait? Are we correct in thinking that unsigned transactions are default rejected before getting to the extrinsic code, unless you explicitly allow them? What is then the real purpose of ensure_signed? We were thinking it would also prevent Root from executing such a transaction.

Lastly, for something called SignedExtension, why is there a validate_unsigned function at all? The trait name would seem to imply it's really just for signed transactions.

We're trying to understand the signed transaction vs. unsigned transaction lifecycle, and what ensure_signed actually does for you.

What it seemed was, if you submitted an unsigned transaction to our pallet that it would put the failed txn in the block because it should fail ensure_signed with BadOrigin, correct? Just like any other failure inside of an extrinsic. IF you assume this, then it's fine for Pays::Yes txns.

However in Pays::No txns, one would think submitting unsigned txns would be an attack vector. Yet running our chain locally, we can submit unsigned txns all day long, and they will never be put in a block as a failed transaction, it will be invalid, because it reaches, (we think) this generated/macro code in validate_unsigned, displaying UnknownTransaction::NoUnsignedValidator in the Polkadot dashboard, without our having to do anything extra.

And in fact if we call this extrinsic using Sudo, it fails with BadOrigin, and the failed transaction is included in a block...so I guess we shouldn't DoS ourselves.

So next, SignedExtension's default validate_unsigned has something very different:

    fn validate_unsigned(
        _call: &Self::Call,
        _info: &DispatchInfoOf<Self::Call>,
        _len: usize,
    ) -> TransactionValidity {
        Ok(ValidTransaction::default())
    }

Basically it seems that unsigned transactions are not calling the above default implementation, but instead the first one which is automagically generated for pallets regardless of whether they have a SignedExtension implemented. Following the code, this expand_outer_validate_unsigned function is called (probably self-evident by now) in construct_runtime.

Question is what is the use of the default for the trait? Are we correct in thinking that unsigned transactions are default rejected before getting to the extrinsic code, unless you explicitly allow them? What is then the real purpose of ensure_signed? We were thinking it would also prevent Root from executing such a transaction.

Lastly, for something called SignedExtension, why is there a validate_unsigned function at all? The trait name would seem to imply it's really just for signed transactions.

We're trying to understand the signed transaction vs. unsigned transaction lifecycle, and what ensure_signed actually does for you.

What it seemed was, if you submitted an unsigned transaction to our pallet that it would put the failed txn in the block because it should fail ensure_signed with BadOrigin, correct? Just like any other failure inside of an extrinsic. IF you assume this, then it's fine for Pays::Yes txns.

However in Pays::No txns, one would think submitting unsigned txns would be an attack vector. Yet running our chain locally, we can submit unsigned txns all day long, and they will never be put in a block as a failed transaction, it will be invalid, because it reaches, (we think) this generated/macro code in validate_unsigned, displaying UnknownTransaction::NoUnsignedValidator in the Polkadot dashboard, without our having to do anything extra.

And in fact if we call this extrinsic using Sudo, it fails with BadOrigin, and the failed transaction is included in a block...so I guess we shouldn't DoS ourselves.

So next, SignedExtension's default validate_unsigned has something very different:

fn validate_unsigned(
    _call: &Self::Call,
    _info: &DispatchInfoOf<Self::Call>,
    _len: usize,
) -> TransactionValidity {
    Ok(ValidTransaction::default())
}

Basically it seems that unsigned transactions are not calling the above default implementation, but instead the first one which is automagically generated for pallets regardless of whether they have a SignedExtension implemented. Following the code, this expand_outer_validate_unsigned function is called (probably self-evident by now) in construct_runtime.

Question is what is the use of the default for the trait? Are we correct in thinking that unsigned transactions are default rejected before getting to the extrinsic code, unless you explicitly allow them? What is then the real purpose of ensure_signed? We were thinking it would also prevent Root from executing such a transaction.

Lastly, for something called SignedExtension, why is there a validate_unsigned function at all? The trait name would seem to imply it's really just for signed transactions.

added 149 characters in body
Source Link

We're trying to understand the signed transaction vs. unsigned transaction lifecycle, and what ensure_signed actually does for you.

What it seemed was, if you submitted an unsigned transaction to our pallet that it would put the failed txn in the block because it should fail ensure_signed with BadOrigin, correct? Just like any other failure inside of an extrinsic. IF you assume this, then it's fine for Pays::Yes txns.

However in Pays::No txns, one would think submitting unsigned txns would be an attack vector. Yet running our chain locally, we can submit unsigned txns all day long, and they will never be put in a block as a failed transaction, it will be invalid, because it reaches, (we think) this generated/macro code in validate_unsigned, displaying UnknownTransaction::NoUnsignedValidator in the Polkadot dashboard, without our having to do anything extra.

And in fact if we call this extrinsic using Sudo, it fails with BadOrigin, and the failed transaction is included in a block...so I guess we shouldn't DoS ourselves.

So next, SignedExtension's default validate_unsigned has something very different:

    fn validate_unsigned(
        _call: &Self::Call,
        _info: &DispatchInfoOf<Self::Call>,
        _len: usize,
    ) -> TransactionValidity {
        Ok(ValidTransaction::default())
    }

Basically it seems that unsigned transactions are not calling the above default implementation, but instead the first one which is automagically generated for pallets regardless of whether they have a SignedExtension implemented. Following the code, this expand_outer_validate_unsigned function is called (probably self-evident by now) in construct_runtime.

Question is what is the use of the default for the trait? Are we correct in thinking that unsigned transactions are default rejected before getting to the extrinsic code, unless you explicitly allow them? What is then the real purpose of ensure_signed? We were thinking it would also prevent Root from executing such a transaction.

Lastly, for something called SignedExtension, why is there a validate_unsigned function at all? The trait name would seem to imply it's really just for signed transactions.

Yes, we are confused :) Please help.

We're trying to understand the signed transaction vs. unsigned transaction lifecycle, and what ensure_signed actually does for you.

What it seemed was, if you submitted an unsigned transaction to our pallet that it would put the failed txn in the block because it should fail ensure_signed correct? Just like any other failure inside of an extrinsic. IF you assume this, then it's fine for Pays::Yes txns.

However in Pays::No txns, one would think submitting unsigned txns would be an attack vector. Yet running our chain locally, we can submit unsigned txns all day long, and they will never be put in a block as a failed transaction, it will be invalid, because it reaches, (we think) this generated/macro code in validate_unsigned, displaying UnknownTransaction::NoUnsignedValidator in the Polkadot dashboard, without our having to do anything extra.

So next, SignedExtension's default validate_unsigned has something very different:

    fn validate_unsigned(
        _call: &Self::Call,
        _info: &DispatchInfoOf<Self::Call>,
        _len: usize,
    ) -> TransactionValidity {
        Ok(ValidTransaction::default())
    }

Basically it seems that unsigned transactions are not calling the above default implementation, but instead the first one which is automagically generated for pallets regardless of whether they have a SignedExtension implemented. Following the code, this expand_outer_validate_unsigned function is called (probably self-evident by now) in construct_runtime.

Question is what is the use of the default for the trait? Are we correct in thinking that unsigned transactions are default rejected before getting to the extrinsic code, unless you explicitly allow them? What is then the real purpose of ensure_signed? We were thinking it would also prevent Root from executing such a transaction.

Lastly, for something called SignedExtension, why is there a validate_unsigned function at all? The trait name would seem to imply it's really just for signed transactions.

Yes, we are confused :) Please help.

We're trying to understand the signed transaction vs. unsigned transaction lifecycle, and what ensure_signed actually does for you.

What it seemed was, if you submitted an unsigned transaction to our pallet that it would put the failed txn in the block because it should fail ensure_signed with BadOrigin, correct? Just like any other failure inside of an extrinsic. IF you assume this, then it's fine for Pays::Yes txns.

However in Pays::No txns, one would think submitting unsigned txns would be an attack vector. Yet running our chain locally, we can submit unsigned txns all day long, and they will never be put in a block as a failed transaction, it will be invalid, because it reaches, (we think) this generated/macro code in validate_unsigned, displaying UnknownTransaction::NoUnsignedValidator in the Polkadot dashboard, without our having to do anything extra.

And in fact if we call this extrinsic using Sudo, it fails with BadOrigin, and the failed transaction is included in a block...so I guess we shouldn't DoS ourselves.

So next, SignedExtension's default validate_unsigned has something very different:

    fn validate_unsigned(
        _call: &Self::Call,
        _info: &DispatchInfoOf<Self::Call>,
        _len: usize,
    ) -> TransactionValidity {
        Ok(ValidTransaction::default())
    }

Basically it seems that unsigned transactions are not calling the above default implementation, but instead the first one which is automagically generated for pallets regardless of whether they have a SignedExtension implemented. Following the code, this expand_outer_validate_unsigned function is called (probably self-evident by now) in construct_runtime.

Question is what is the use of the default for the trait? Are we correct in thinking that unsigned transactions are default rejected before getting to the extrinsic code, unless you explicitly allow them? What is then the real purpose of ensure_signed? We were thinking it would also prevent Root from executing such a transaction.

Lastly, for something called SignedExtension, why is there a validate_unsigned function at all? The trait name would seem to imply it's really just for signed transactions.

Source Link

Difference between SignedExtension default behavior vs. actual behavior (expand_outer_validate_unsigned)

We're trying to understand the signed transaction vs. unsigned transaction lifecycle, and what ensure_signed actually does for you.

What it seemed was, if you submitted an unsigned transaction to our pallet that it would put the failed txn in the block because it should fail ensure_signed correct? Just like any other failure inside of an extrinsic. IF you assume this, then it's fine for Pays::Yes txns.

However in Pays::No txns, one would think submitting unsigned txns would be an attack vector. Yet running our chain locally, we can submit unsigned txns all day long, and they will never be put in a block as a failed transaction, it will be invalid, because it reaches, (we think) this generated/macro code in validate_unsigned, displaying UnknownTransaction::NoUnsignedValidator in the Polkadot dashboard, without our having to do anything extra.

So next, SignedExtension's default validate_unsigned has something very different:

    fn validate_unsigned(
        _call: &Self::Call,
        _info: &DispatchInfoOf<Self::Call>,
        _len: usize,
    ) -> TransactionValidity {
        Ok(ValidTransaction::default())
    }

Basically it seems that unsigned transactions are not calling the above default implementation, but instead the first one which is automagically generated for pallets regardless of whether they have a SignedExtension implemented. Following the code, this expand_outer_validate_unsigned function is called (probably self-evident by now) in construct_runtime.

Question is what is the use of the default for the trait? Are we correct in thinking that unsigned transactions are default rejected before getting to the extrinsic code, unless you explicitly allow them? What is then the real purpose of ensure_signed? We were thinking it would also prevent Root from executing such a transaction.

Lastly, for something called SignedExtension, why is there a validate_unsigned function at all? The trait name would seem to imply it's really just for signed transactions.

Yes, we are confused :) Please help.