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

Fix waiting init message is not appended to wait list #3705

Closed
grishasobol opened this issue Jan 30, 2024 · 1 comment · Fixed by #3812
Closed

Fix waiting init message is not appended to wait list #3705

grishasobol opened this issue Jan 30, 2024 · 1 comment · Fixed by #3812
Assignees
Labels
C0-bug Something isn't working

Comments

@grishasobol
Copy link
Member

grishasobol commented Jan 30, 2024

Problem

There can be some cases when waiting init message is not going to be appended into wait list because of lock of gas.

} else {
maximal_hold
};
// Validating duration.
if hold.expected_duration().is_zero() {
// TODO: Replace with unreachable call after:
// - `HoldBound` safety usage stabilized;
log::error!("Failed to figure out correct wait hold bound");
return;
}

This log::error can be called in case message have not enough gas to be added in the wait list. In most cases this is restricted by core-processor checks, but it does not protect cases when message will be added to waiting init list.
So, if some program or user will send error to uninitialised program with specific amount of gas, than message will be forgotten. So, it will be never consumed and gas node will stay forever in storage.

Steps

You can try this test in pallet-gear:

#[test]
fn calculate_gas_waiting_init() {
    let wat = r#"
        (module
            (import "env" "memory" (memory 1))
            (import "env" "gr_wait_up_to" (func $wait (param i32)))
            (import "env" "gr_program_id" (func $program_id (param i32)))
            (import "env" "gr_send" (func $send (param i32 i32 i32 i32 i32)))
            (export "init" (func $init))
            (func $init
                (call $program_id (i32.const 0))
                (call $send (i32.const 0) (i32.const 0) (i32.const 1) (i32.const 0) (i32.const 1000))
                (call $wait (i32.const 1))
            )
        )"#;

    init_logger();
    new_test_ext().execute_with(|| {
        let pid = Gear::upload_program(
            RuntimeOrigin::signed(USER_1),
            ProgramCodeKind::Custom(wat).to_bytes(),
            DEFAULT_SALT.to_vec(),
            EMPTY_PAYLOAD.to_vec(),
            210_105_500,
            0,
            false,
        )
        .map(|_| get_last_program_id())
        .expect("Program uploading failed");

        run_to_block(4, None);
    });
}

Gas limit amount 210_105_500 has been found, so that the case would happen.

Possible Solution

  1. Remove waiting init list and reply with error for all messages, that are sent to uninitialised program.
  2. In case we cannot put message to the wait list then reply with an error.
@grishasobol
Copy link
Member Author

take also #3707 in account

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C0-bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants