From e74aa7ef09e22a6d135a0c19af80ac1331f750a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 18 Mar 2021 21:54:35 +0100 Subject: [PATCH 1/3] api: Document StateReplay replaced message behavior --- api/api_full.go | 17 ++++++++++++++++- documentation/en/api-methods.md | 17 ++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index cbd23564616..63a7e81f75d 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -350,7 +350,22 @@ type FullNode interface { // tipset. StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) // StateReplay replays a given message, assuming it was included in a block in the specified tipset. - // If no tipset key is provided, the appropriate tipset is looked up. + // + // If a tipset key is provided, and a replacing message is found on chain, + // the method will return an error saying that the message wasn't found + // + // If no tipset key is provided, the appropriate tipset is looked up, and if + // the message was gas-repriced, the on-chain message will be replayed - in + // that case the returned InvocResult.MsgCid will not match the Cid param + // + // If the caller wants to ensure that exactly the requested message was executed, + // they MUST check that InvocResult.MsgCid is equal to the provided Cid. + // Without this check both the requested and original message may appear as + // successfully executed on-chain, which may look like a double-spend. + // + // A replacing message is a message with a different CID, any of Gas values, and + // different signature, but with all other parameters matching (source/destination, + // nonce, params, etc.) StateReplay(context.Context, types.TipSetKey, cid.Cid) (*InvocResult, error) // StateGetActor returns the indicated actor's nonce and balance. StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 34b94ff4403..458210bf8d7 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -4459,7 +4459,22 @@ Response: ### StateReplay StateReplay replays a given message, assuming it was included in a block in the specified tipset. -If no tipset key is provided, the appropriate tipset is looked up. + +If a tipset key is provided, and a replacing message is found on chain, +the method will return an error saying that the message wasn't found + +If no tipset key is provided, the appropriate tipset is looked up, and if +the message was gas-repriced, the on-chain message will be replayed - in +that case the returned InvocResult.MsgCid will not match the Cid param + +If the caller wants to ensure that exactly the requested message was executed, +they MUST check that InvocResult.MsgCid is equal to the provided Cid. +Without this check both the requested and original message may appear as +successfully executed on-chain, which may look like a double-spend. + +A replacing message is a message with a different CID, any of Gas values, and +different signature, but with all other parameters matching (source/destination, +nonce, params, etc.) Perms: read From 82e019bd366c4f255c2d8f78b28f997e37671f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 18 Mar 2021 22:12:22 +0100 Subject: [PATCH 2/3] api: Note that ChainGetBlockMessages is not the method to use most of the time --- api/api_full.go | 11 +++++++++++ documentation/en/api-methods.md | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/api/api_full.go b/api/api_full.go index 63a7e81f75d..41efa8077b7 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -67,6 +67,17 @@ type FullNode interface { ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) // ChainGetBlockMessages returns messages stored in the specified block. + // + // Note: If there are multiple blocks in a tipset, it's likely that some + // messages will be duplicated. It's also possible for blocks in a tipset to have + // different messages from the same sender at the same nonce. When that happens, + // only the first message (in a block with lowest ticket) will be considered + // for execution + // + // NOTE: THIS METHOD SHOULD ONLY BE USED FOR GETTING MESSAGES IN A SPECIFIC BLOCK + // + // DO NOT USE THIS METHOD TO GET MESSAGES INCLUDED IN A TIPSET + // Use ChainGetParentMessages, which will perform correct message deduplication ChainGetBlockMessages(ctx context.Context, blockCid cid.Cid) (*BlockMessages, error) // ChainGetParentReceipts returns receipts for messages in parent tipset of diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 458210bf8d7..d0e1bc22e7b 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -425,6 +425,17 @@ Response: ### ChainGetBlockMessages ChainGetBlockMessages returns messages stored in the specified block. +Note: If there are multiple blocks in a tipset, it's likely that some +messages will be duplicated. It's also possible for blocks in a tipset to have +different messages from the same sender at the same nonce. When that happens, +only the first message (in a block with lowest ticket) will be considered +for execution + +NOTE: THIS METHOD SHOULD ONLY BE USED FOR GETTING MESSAGES IN A SPECIFIC BLOCK + +DO NOT USE THIS METHOD TO GET MESSAGES INCLUDED IN A TIPSET +Use ChainGetParentMessages, which will perform correct message deduplication + Perms: read From da10ef2e36ddf92c4a623a47e02d4828056165cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 19 Mar 2021 12:57:59 +0100 Subject: [PATCH 3/3] api: Better StateCompute docs --- api/api_full.go | 34 +++++++++++++++++++++++++++++++-- documentation/en/api-methods.md | 32 ++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 41efa8077b7..022f5b1873a 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -520,7 +520,7 @@ type FullNode interface { // NOTE: If the requested message was replaced, this method will return the receipt // for the replacing message - if the caller needs the receipt for exactly the // requested message, use StateSearchMsg().Receipt, and check that MsgLookup.Message - // is matching the requseted CID + // is matching the requested CID // // DEPRECATED: Use StateSearchMsg, this method won't be supported in v1 API StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) @@ -528,7 +528,37 @@ type FullNode interface { StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error) // StateCompute is a flexible command that applies the given messages on the given tipset. // The messages are run as though the VM were at the provided height. - StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error) + // + // When called, StateCompute will: + // - Load the provided tipset, or use the current chain head if not provided + // - Compute the tipset state of the provided tipset on top of the parent state + // - (note that this step runs before vmheight is applied to the execution) + // - Execute state upgrade if any were scheduled at the epoch, or in null + // blocks preceding the tipset + // - Call the cron actor on null blocks preceding the tipset + // - For each block in the tipset + // - Apply messages in blocks in the specified + // - Award block reward by calling the reward actor + // - Call the cron actor for the current epoch + // - If the specified vmheight is higher than the current epoch, apply any + // needed state upgrades to the state + // - Apply the specified messages to the state + // + // The vmheight parameter sets VM execution epoch, and can be used to simulate + // message execution in different network versions. If the specified vmheight + // epoch is higher than the epoch of the specified tipset, any state upgrades + // until the vmheight will be executed on the state before applying messages + // specified by the user. + // + // Note that the initial tipset state computation is not affected by the + // vmheight parameter - only the messages in the `apply` set are + // + // If the caller wants to simply compute the state, vmheight should be set to + // the epoch of the specified tipset. + // + // Messages in the `apply` parameter must have the correct nonces, and gas + // values set. + StateCompute(ctx context.Context, vmheight abi.ChainEpoch, apply []*types.Message, tsk types.TipSetKey) (*ComputeStateOutput, error) // StateVerifierStatus returns the data cap for the given address. // Returns nil if there is no entry in the data cap table for the // address. diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index d0e1bc22e7b..39f45c9fbac 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -3577,6 +3577,36 @@ Response: `"0"` StateCompute is a flexible command that applies the given messages on the given tipset. The messages are run as though the VM were at the provided height. +When called, StateCompute will: +- Load the provided tipset, or use the current chain head if not provided +- Compute the tipset state of the provided tipset on top of the parent state + - (note that this step runs before vmheight is applied to the execution) + - Execute state upgrade if any were scheduled at the epoch, or in null + blocks preceding the tipset + - Call the cron actor on null blocks preceding the tipset + - For each block in the tipset + - Apply messages in blocks in the specified + - Award block reward by calling the reward actor + - Call the cron actor for the current epoch +- If the specified vmheight is higher than the current epoch, apply any + needed state upgrades to the state +- Apply the specified messages to the state + +The vmheight parameter sets VM execution epoch, and can be used to simulate +message execution in different network versions. If the specified vmheight +epoch is higher than the epoch of the specified tipset, any state upgrades +until the vmheight will be executed on the state before applying messages +specified by the user. + +Note that the initial tipset state computation is not affected by the +vmheight parameter - only the messages in the `apply` set are + +If the caller wants to simply compute the state, vmheight should be set to +the epoch of the specified tipset. + +Messages in the `apply` parameter must have the correct nonces, and gas +values set. + Perms: read @@ -3704,7 +3734,7 @@ matching gas-repriced replacing message NOTE: If the requested message was replaced, this method will return the receipt for the replacing message - if the caller needs the receipt for exactly the requested message, use StateSearchMsg().Receipt, and check that MsgLookup.Message -is matching the requseted CID +is matching the requested CID DEPRECATED: Use StateSearchMsg, this method won't be supported in v1 API