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

restore get_block_header_state endpoint for usage both pre and post Savanna activation #2311

Closed

Conversation

spoonincode
Copy link
Member

@spoonincode spoonincode commented Mar 14, 2024

get_block_header_state returns the pre-Savanna (legacy) block header state. Parts of this response are incompatible with the internals of the new Savanna block state. Originally the plan was to simply remove the get_block_header_state endpoint, but some versions of eosjs (including the latest one, 22.1.0, apparently downloaded some 17k times in the last week) require operation of this endpoint given certain values of blocksBehind otherwise eosjs will be unable to push a transaction.

So instead, restore the endpoint with some important restrictions. Prior to Savanna activation the endpoint will continue to -- strictly for reversible blocks -- return the entire legacy block header state as it does today. But after activation of Savanna, it will return a response containing all fields but with only block_num, id, header, and additional_signatures filled out. Other fields will still exist but will be empty or zero. Additionally, the endpoint will consider both reversible and irreversible blocks if the request used a block number. This latter tweak helps guard against a race condition in eosjs between calling get_info and then get_block_header_state when blocksBehind is a low number such as 2 or 3.

An example post Savanna activated response with the limited filled fields looks something like,

{
  "block_num": 40660,
  "dpos_proposed_irreversible_blocknum": 0,
  "dpos_irreversible_blocknum": 0,
  "active_schedule": {
    "version": 0,
    "producers": []
  },
  "blockroot_merkle": {
    "_active_nodes": [],
    "_node_count": 0
  },
  "producer_to_last_produced": [],
  "producer_to_last_implied_irb": [],
  "valid_block_signing_authority": [
    0,
    {
      "threshold": 0,
      "keys": []
    }
  ],
  "confirm_count": [],
  "id": "00009ed4aa662f3d7e96d88061e4741692b433fe783befc6c3cb6c6a40c5955a",
  "header": {
    "timestamp": "2024-03-19T02:39:40.000",
    "producer": "inita",
    "confirmed": 0,
    "previous": "00009ed38d8d4c103ce5ced75558d6ac0f4d2ac4b63cf964feeb6d8bce600ade",
    "transaction_mroot": "0000000000000000000000000000000000000000000000000000000000000000",
    "action_mroot": "b179283d2264aa663cb669924bbff2f33e81a7ed71dcb465342673602605a1f1",
    "schedule_version": 2,
    "header_extensions": [
      [
        2,
        "d39e0000010000"
      ]
    ],
    "producer_signature": "SIG_K1_KgufADyFuHdBwT6VGBVdrnhVs6dakZdXp4qr5NgJFU7orfXbFi9eVc7NvjrjvUyL79SXfMjgyzW7cVGfQW8iy1CbjStENZ"
  },
  "pending_schedule": {
    "schedule_lib_num": 0,
    "schedule_hash": "0000000000000000000000000000000000000000000000000000000000000000",
    "schedule": {
      "version": 0,
      "producers": []
    }
  },
  "activated_protocol_features": null,
  "additional_signatures": []
}

I've confirmed with eosjs 22.1.0, 21.0.4, and 20.0.3 that operation works as expected. (20.0.3 does not use get_block_header_state for transact() though, instead just always calling get_block)

Resolves AntelopeIO/spring#39

@@ -1063,6 +1063,36 @@ struct controller_impl {
});
}

template <typename F>
std::optional<block_header_state_legacy> fetch_bhs_for_legacy_rpc_by_x(F&& f, const std::optional<block_num_type> block_num = std::nullopt) const {
Copy link
Member Author

Choose a reason for hiding this comment

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

It feels wrong for logic specific to how an RPC endpoint operates to be in controller (instead of the chain_plugin leveraging more generic calls against controller), but controller seems to be in the best position to create something concise with forkdb & apply()

Copy link
Member

@heifner heifner Mar 19, 2024

Choose a reason for hiding this comment

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

We are trying to keep block_header_state and block_header_state_legacy from leaking out of controller. Seems like this should return a signed_block_ptr and move the extraction of data into chain_plugin. You should then be able to just use the existing fetch_block_by_id and fetch_block_by_number. Seems to me we can return the same data pre/post Savanna.

};

set_finalizers(policy_input);
produce_blocks(10);
Copy link
Member Author

Choose a reason for hiding this comment

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

Test could use some love around the call's behavior during the transition -- what I guess is the new both forkdb situation will handle -- when that is added.

Base automatically changed from gh_2285 to hotstuff_integration March 15, 2024 17:38
@ericpassmore
Copy link
Contributor

ericpassmore commented Mar 15, 2024

Note:start
group: PROTOCOL
category: HTTP
summary: Updates get_block_header_state with a minimum set of entries to continue to support eosjs TAPOS calculations.
Note:end

@@ -1063,6 +1063,36 @@ struct controller_impl {
});
}

template <typename F>
std::optional<block_header_state_legacy> fetch_bhs_for_legacy_rpc_by_x(F&& f, const std::optional<block_num_type> block_num = std::nullopt) const {
Copy link
Member

@heifner heifner Mar 19, 2024

Choose a reason for hiding this comment

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

We are trying to keep block_header_state and block_header_state_legacy from leaking out of controller. Seems like this should return a signed_block_ptr and move the extraction of data into chain_plugin. You should then be able to just use the existing fetch_block_by_id and fetch_block_by_number. Seems to me we can return the same data pre/post Savanna.

@spoonincode
Copy link
Member Author

After some side band discussion, we want to go with a different approach: always behave the same both pre & post Savanna by returning an elided block_header_state_legacy over the API endpoint (and always from both reversible and irreversible). Since it's mostly a re-do at this point, going to close this PR for replacement with new one.

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.

Change get_block_header_state for EOSJS support
3 participants