-
Notifications
You must be signed in to change notification settings - Fork 19
Support for reconcile confirmation against the in-memory canonical chain #174
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
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
Co-authored-by: alexey semenyuk <alexsemenyuk88@gmail.com> Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, looks really good - a few questions and suggestions but thanks for all the comments in the flow
// Note: should consider have an in-memory map of transaction hash to block for faster lookup | ||
// The extra memory usage of the map should be outweighed by the speed improvement of lookup | ||
// But I saw we have a ffcapi.MinimalBlockInfo struct that intentionally removes the tx hashes | ||
// so need to figure out the reason first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you going to do this figuring out as part of the PR? I did wonder why the TX hash -> block was not a thing
} | ||
|
||
// Compare the existing confirmation queue with the in-memory linked list | ||
bl.compareAndUpdateConfirmationQueue(ctx, occ, txBlockInfo, targetConfirmationCount) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no error ?
|
||
chainHead := bl.canonicalChain.Front().Value.(*ffcapi.MinimalBlockInfo) | ||
chainTail := bl.canonicalChain.Back().Value.(*ffcapi.MinimalBlockInfo) | ||
if chainHead == nil || chainTail == nil || chainTail.BlockNumber.Uint64() < txBlockNumber { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we check that the canonical chain's tail (oldest block) is smaller than the TX block number - that could happen and still be correct to carry on no? or is the tail the newest block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or did you mean to check the chainHead?
} | ||
} | ||
|
||
func (bl *blockListener) initializeConfirmationMap(occ *ffcapi.ConfirmationMapUpdateResult, txBlockInfo *ffcapi.MinimalBlockInfo) []*ffcapi.MinimalBlockInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this occ
naming format? maybe confMapResult to keep with txBlockInfo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah it's output context, but it's not a like a OutputContext object that is why the confusion
return existingQueue | ||
} | ||
|
||
func (bl *blockListener) processExistingConfirmations(ctx context.Context, occ *ffcapi.ConfirmationMapUpdateResult, txBlockInfo *ffcapi.MinimalBlockInfo, existingQueue []*ffcapi.MinimalBlockInfo, chainHead *ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) ([]*ffcapi.MinimalBlockInfo, *list.Element) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a nit so up to you but maybe to reduce number of params as you have done in the past having a context object with all the things we need
} | ||
|
||
// If we've trimmed off all the existing confirmations, we need to add the canonical chain head | ||
// to tell use the head block we used to confirmed the transaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// to tell use the head block we used to confirmed the transaction | |
// to tell us the head block we used to confirm the transaction |
confirmationBlockNumber := txBlockNumber + targetConfirmationCount | ||
if lastBlockInNewQueue.BlockNumber.Uint64() >= confirmationBlockNumber { | ||
chainHead := bl.canonicalChain.Front().Value.(*ffcapi.MinimalBlockInfo) | ||
// we've got a confirmable so whether the rest of the chain has forked is not longer relevant |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// we've got a confirmable so whether the rest of the chain has forked is not longer relevant | |
// we've got a confirmation so whether the rest of the chain has forked is no longer relevant |
) | ||
} | ||
|
||
func (bl *blockListener) validateExistingConfirmations(ctx context.Context, occ *ffcapi.ConfirmationMapUpdateResult, newQueue []*ffcapi.MinimalBlockInfo, existingConfirmations []*ffcapi.MinimalBlockInfo, currentBlock *list.Element, chainHead *ffcapi.MinimalBlockInfo, txBlockInfo *ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) ([]*ffcapi.MinimalBlockInfo, *list.Element) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function was quite difficult to follow FYI
existingQueue := bl.initializeConfirmationMap(occ, txBlockInfo) | ||
|
||
// Validate and process existing confirmations | ||
newQueue, currentBlock := bl.processExistingConfirmations(ctx, occ, txBlockInfo, existingQueue, chainHead, targetConfirmationCount) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this name of currentBlock
is quite confusing... I get the name cause it can be the front of the chain, the block at which the confirmation reached the limit...
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
Requires hyperledger/firefly-transaction-manager#148
This PR introduced a new method,
ReconcileConfirmationsForTransaction,
which can be used to directly calculate the confirmation map of a given transaction.The diagram below shows the core logic of the function:

Details of the confirmation Map struct can be found in this PR: hyperledger/firefly-transaction-manager#148
Reconciliation logic for an existing confirmations that get passed in
newFork
flag will be set to true in the response accordinglyConfirmation queue for different scenarios: