Skip to content
This repository has been archived by the owner on May 22, 2023. It is now read-only.

Redemption flow actions #585

Merged
merged 34 commits into from
Nov 9, 2020
Merged

Redemption flow actions #585

merged 34 commits into from
Nov 9, 2020

Conversation

lukasz-zimnoch
Copy link
Member

@lukasz-zimnoch lukasz-zimnoch commented Oct 22, 2020

Refs: #574
Depends on: #580
Depends on: keep-network/tbtc#740

This pull request expands the TBTC extension by adding two new actions specific to the deposit redemption flow.
Here is a brief summary of both actions:

ProvideRedemptionSignature action

ProvideRedemptionProof action

  • Starts the monitoring on new GotRedemptionSignature event. This event occurs once provideRedemptionSignature contract method is called.
  • Stops the monitoring if RedemptionRequested or Redeemed event occurs for the observed deposit. These events can be emitted by increaseRedemptionFee or provideRedemptionProof respectively.
  • Performs the increaseRedemptionFee action once the deposit is close to exceeding the redemption proof timeout. This part will be extended soon by adding the ability of submitting the redemption proof directy if the BTC transaction exists.

Added a stub of the provide redemption signature
monitoring process. Also, implemented an events
log which will be needed at later stage.
@lukasz-zimnoch lukasz-zimnoch changed the title Stub of the provide redemption signature action Redemption flow actions Oct 22, 2020
Implemented the main part of the redemption
signature action.
Base automatically changed from app-specific-actions to master October 23, 2020 08:48
# Conflicts:
#	pkg/extensions/tbtc/tbtc.go
@pdyraga pdyraga added this to the v1.5.0 milestone Oct 23, 2020
pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
}

return fmt.Errorf(
"could not find signature for digest: [%v]",
Copy link
Member

Choose a reason for hiding this comment

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

Worth confirming at some point if the digest is logged in a human-readable form this way.

pkg/chain/ethereum/tbtc.go Outdated Show resolved Hide resolved
pkg/chain/ethereum/tbtc.go Outdated Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Show resolved Hide resolved
if err != nil {
return nil, err
}

Copy link
Member

Choose a reason for hiding this comment

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

Hate to say that but I think we need to block this function here for some time (6-12 blocks) and check the chain before we signal the monitoring goroutine to stop. In case of a chain reorganizaion, we may get an event, stop monitoring, but the final chain state may not include the transaction with the redemption signature provided. In this case, our monitoring goroutine should act. I am not sure yet how it impacts the timeouts and exponential backoff for retries.

The same comment applies to all monitoringStopFn implementations.

If this suggestion does not lead to changing the code structure significantly - and I think it does not - I am fine with just leaving a TODO here and addressing this and all other monitoringStopFn implementations in a separate PR. Leaving the decision to you.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd vote for a separate PR. This one is already big enough.

Copy link
Member

Choose a reason for hiding this comment

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

Sure, let's just leave a TODO for now.

Copy link
Member

Choose a reason for hiding this comment

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

Handled in #591 but I'll this discussion open here until that PR is reviewed and merged.

pkg/extensions/tbtc/tbtc.go Show resolved Hide resolved

redemptionRequestedEvents, err := t.chain.PastDepositRedemptionRequestedEvents(
depositAddress,
0, // TODO: Should be something better that 0
Copy link
Member

Choose a reason for hiding this comment

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

This could make all clients deployed against Infura unhappy. As far as I know, they allow to reach no more than 1000 blocks in the past and assuming each block takes 15sec on average to mine, this is just 250 minutes back.

If there is no workaround, without seriously sacrificing code quality, we are fine. Just raising a concern.

Copy link
Member Author

Choose a reason for hiding this comment

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

Unfortunately, the approach presented here is the safest and simplest one. We can cache incoming events as an alternative but given event duplications, chain reorgs and stuff, I want to avoid caching as it strongly complicates the code.

Copy link
Member

Choose a reason for hiding this comment

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

I had to think more about it and load entire context into my brain. More thoughts on that:

  • We need duplicate event filtering for monitoringStartFn. The monitoring we should go with could be a time cache with a relatively short expiration time informing about the fact we triggered action X for deposit Y. If we know there is a pending X:Y monitoring, we do not start a new one. It is not yet clear to me what the expiration time should be but I guess the time needed to mine 6-12 blocks should be enough.

    I think this approach is better than e.g. filtering out events by digest or any other property, as it's aligned with the approach proposed currently for actFn, and this way, we do not need to care about forks and two different events for the same notification in the competing branches.

  • We should not wait for any confirmations in monitoringStartFn as there is a chance we'll lose events from monitoringStopFn. If we are not already monitoring X:Y, let's start a goroutine immediately.

  • We should wait for 6-12 block confirmations in monitoringStopFn before we decide to stop the monitoring routine.

  • I like we are stateless actFn and we don't care about the particular event instance but we are oriented in the context of deposit and monitoring of a certain state transition.

  • Once we act in actFn we should wait for 6-12 blocks and check the state of the deposit. We need to make sure our transaction has enough confirmations.

Copy link
Member Author

@lukasz-zimnoch lukasz-zimnoch Oct 29, 2020

Choose a reason for hiding this comment

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

I've added the link to this discussion to the TODOs section where I listed all the things related to events deduplication, reorgs etc.

Copy link
Member

Choose a reason for hiding this comment

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

Leaving this discussion open until all follow-up PRs addressing those issues are reviewed and merged.

pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
@lukasz-zimnoch lukasz-zimnoch marked this pull request as ready for review October 27, 2020 14:01
@lukasz-zimnoch
Copy link
Member Author

@pdyraga added the unit tests and addressed all comments! I'm ready for the next look.

@@ -20,7 +20,7 @@ require (
github.com/ipfs/go-log v1.0.4
github.com/keep-network/keep-common v1.2.1-0.20201020114759-19c123cbd4f4
github.com/keep-network/keep-core v1.3.0
github.com/keep-network/tbtc v1.1.1-0.20201020115551-5f9077c74826
github.com/keep-network/tbtc v1.1.1-0.20201026093513-cb9246987718
Copy link
Member

Choose a reason for hiding this comment

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

We still need to implement a solution in keep-common for a workaround in keep-network/tbtc#740 before merging this PR, right? Otherwise, we would end up with a situation where keep-ecdsa master would not build against tbtc master.

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope, we don't have to do anything in keep-common.

Copy link
Member

Choose a reason for hiding this comment

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

Don't we need generators for eventlog? From the description of the referenced PR:

Added a TBTCSystemEventLog allowing to access past events emitted by the TBTCSystem contract. This is a temporary workaround because contract bindings generated by the keep-common generator don't support this feature yet.

Copy link
Member Author

Choose a reason for hiding this comment

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

We just need the abi file which is already generated and tracked by the VCS.

Copy link
Member

Choose a reason for hiding this comment

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

We do need to implement a change to the generator in keep-common so that it generates TBTCSystemEventLog, correct?

Let me put it this way:

We build tBTC go package from scratch:

  • we remove all generated files from pkg/chain/ethereum/gen
  • we do go generate ./... there
  • we push a new version

Then we build keep-ecdsa:

  • we update a dependency to tbtc
  • we run go build

My understanding is that the compilation will fail because TBTCSystemEventLog will not be there.

In other words, we are depending on a file that should be generated but it's not generated.

Copy link
Member Author

Choose a reason for hiding this comment

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

Not quite. Eventually, we should extend the existing keep-common generator in that way it generates the Filter* methods straight into the TBTCSystem binding struct. TBTCSystemEventLog is just a temporary workaround created manually without using the generator. It is also tracked by VCS similarly as the regular bindings. So, when we build tBTC package from scratch we shouldn't delete anything. We should only run go generate ./... to capture possible contract changes.

Copy link
Member

Choose a reason for hiding this comment

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

Right. So just to be clear - I am absolutely fine with merging this PR having TBTCSystemEventLog created manually just like now but I do not want to release a new version before we have this file generated or having Filter* methods generated into TBTCSystem struct.

Copy link
Member

Choose a reason for hiding this comment

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

I'll leave this discussion open until the proper solution is implemented. I do not want to block this PR, though.

go.sum Show resolved Hide resolved
pkg/chain/chain.go Show resolved Hide resolved
pkg/chain/ethereum/connect.go Show resolved Hide resolved
if err != nil {
return nil, err
}

Copy link
Member

Choose a reason for hiding this comment

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

Sure, let's just leave a TODO for now.


redemptionRequestedEvents, err := t.chain.PastDepositRedemptionRequestedEvents(
depositAddress,
0, // TODO: Should be something better that 0
Copy link
Member

Choose a reason for hiding this comment

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

I had to think more about it and load entire context into my brain. More thoughts on that:

  • We need duplicate event filtering for monitoringStartFn. The monitoring we should go with could be a time cache with a relatively short expiration time informing about the fact we triggered action X for deposit Y. If we know there is a pending X:Y monitoring, we do not start a new one. It is not yet clear to me what the expiration time should be but I guess the time needed to mine 6-12 blocks should be enough.

    I think this approach is better than e.g. filtering out events by digest or any other property, as it's aligned with the approach proposed currently for actFn, and this way, we do not need to care about forks and two different events for the same notification in the competing branches.

  • We should not wait for any confirmations in monitoringStartFn as there is a chance we'll lose events from monitoringStopFn. If we are not already monitoring X:Y, let's start a goroutine immediately.

  • We should wait for 6-12 block confirmations in monitoringStopFn before we decide to stop the monitoring routine.

  • I like we are stateless actFn and we don't care about the particular event instance but we are oriented in the context of deposit and monitoring of a certain state transition.

  • Once we act in actFn we should wait for 6-12 blocks and check the state of the deposit. We need to make sure our transaction has enough confirmations.

pkg/chain/event.go Outdated Show resolved Hide resolved
pkg/chain/local/bonded_ecdsa_keep_test.go Show resolved Hide resolved
const maxActAttempts = 3
const (
maxActAttempts = 3
pastEventsLookbackBlocks = 10000
Copy link
Member

Choose a reason for hiding this comment

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

Why don't we pass the block number from which the monitoring started to actFn? We can get the block number from the event in monitoringStartFn.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is possible but I'm afraid this can lead to some problems in the future. I'm not sure if we can safely rely on blocks numbers taken from events due to some weird things which may happen like event duplications or chain reorgs. Also, this will work for all actions but provideRedemptionProof which should look in the past beyond the monitoring start block. Taking those concerns in account, I think the safest and simplest way is just start from block current - 10k

Copy link
Member

Choose a reason for hiding this comment

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

We can leave it like that for now. A little concerned about how much it costs to scan 10k previous blocks for operators using 3rd party Ethereum providers who charge by compute unit but we can revise in the future.

Copy link
Member Author

Choose a reason for hiding this comment

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

IIRC, it's always one eth_getLogs call if we are talking about the number of requests.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, though it sometimes does not matter if it's just one call but how expensive was to compute a respose for this call.

pkg/extensions/tbtc/tbtc.go Outdated Show resolved Hide resolved
pkg/chain/local/local.go Outdated Show resolved Hide resolved
pkg/chain/local/local.go Outdated Show resolved Hide resolved
pkg/chain/local/local.go Outdated Show resolved Hide resolved
pkg/chain/local/local_test.go Show resolved Hide resolved
pkg/extensions/tbtc/tbtc.go Show resolved Hide resolved
pkg/extensions/tbtc/tbtc_test.go Show resolved Hide resolved
@pdyraga pdyraga merged commit 5498656 into master Nov 9, 2020
@pdyraga pdyraga deleted the redemption-actions branch November 9, 2020 16:43
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants