From 4f65f76eb9eb782608eacfc536653929eb20990d Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 10 Sep 2025 13:20:26 +0100 Subject: [PATCH 01/12] adding a new function for reconciling confirmations map Signed-off-by: Chengxuan Xing --- go.mod | 2 +- go.sum | 28 ++------------- mocks/apiclientmocks/fftm_client.go | 2 +- mocks/confirmationsmocks/manager.go | 2 +- mocks/eventsmocks/stream.go | 2 +- mocks/ffcapimocks/api.go | 32 ++++++++++++++++- mocks/metricsmocks/event_metrics_emitter.go | 2 +- .../transaction_handler_metrics.go | 2 +- mocks/persistencemocks/persistence.go | 2 +- mocks/persistencemocks/rich_query.go | 2 +- .../transaction_persistence.go | 2 +- .../managed_tx_event_handler.go | 2 +- mocks/txhandlermocks/transaction_handler.go | 2 +- mocks/wsmocks/web_socket_channels.go | 2 +- mocks/wsmocks/web_socket_server.go | 2 +- pkg/ffcapi/api.go | 35 +++++++++++++++++++ pkg/fftm/manager.go | 4 +++ pkg/fftm/transaction_management.go | 5 +++ pkg/fftm/transaction_management_test.go | 21 +++++++++++ 19 files changed, 111 insertions(+), 40 deletions(-) diff --git a/go.mod b/go.mod index a3ba7b74..1467bf0b 100644 --- a/go.mod +++ b/go.mod @@ -97,4 +97,4 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect -) \ No newline at end of file +) diff --git a/go.sum b/go.sum index 4db9269b..47f324dc 100644 --- a/go.sum +++ b/go.sum @@ -40,18 +40,12 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/getkin/kin-openapi v0.122.0 h1:WB9Jbl0Hp/T79/JF9xlSW5Kl9uYdk/AWD0yAd9HOM10= -github.com/getkin/kin-openapi v0.122.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw= github.com/getkin/kin-openapi v0.131.0 h1:NO2UeHnFKRYhZ8wg6Nyh5Cq7dHk4suQQr72a4pMrDxE= github.com/getkin/kin-openapi v0.131.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR8= -github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= @@ -96,8 +90,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hyperledger/firefly-common v1.4.11 h1:WKv2hQuNpS7yP51THxzpzrqU3jkln23C9vq5iminzBk= -github.com/hyperledger/firefly-common v1.4.11/go.mod h1:E7w/RxNtVnX52WXLQW9f2xVAgZnW70voZeE9sZrx/q0= github.com/hyperledger/firefly-common v1.5.5 h1:UaANgBIT0aBvAk0Yt+Qrn6qXxpwNIrFfwnW3EBivrQs= github.com/hyperledger/firefly-common v1.5.5/go.mod h1:1Xawm5PUhxT7k+CL/Kr3i1LE3cTTzoQwZMLimvlW8rs= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -189,10 +181,8 @@ github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lne github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -223,8 +213,6 @@ github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMV github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -255,8 +243,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e h1:723BNChdd0c2Wk6WOE320qGBiPtYx0F0Bbm1kriShfE= @@ -276,8 +262,6 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -306,8 +290,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -316,8 +298,6 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -328,8 +308,6 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -350,8 +328,6 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/mocks/apiclientmocks/fftm_client.go b/mocks/apiclientmocks/fftm_client.go index 56b05cd4..e4db93b7 100644 --- a/mocks/apiclientmocks/fftm_client.go +++ b/mocks/apiclientmocks/fftm_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package apiclientmocks diff --git a/mocks/confirmationsmocks/manager.go b/mocks/confirmationsmocks/manager.go index 249dc4bc..252878c4 100644 --- a/mocks/confirmationsmocks/manager.go +++ b/mocks/confirmationsmocks/manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package confirmationsmocks diff --git a/mocks/eventsmocks/stream.go b/mocks/eventsmocks/stream.go index e41536bc..db0c72f1 100644 --- a/mocks/eventsmocks/stream.go +++ b/mocks/eventsmocks/stream.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package eventsmocks diff --git a/mocks/ffcapimocks/api.go b/mocks/ffcapimocks/api.go index db3d338e..f8451d9f 100644 --- a/mocks/ffcapimocks/api.go +++ b/mocks/ffcapimocks/api.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package ffcapimocks @@ -663,6 +663,36 @@ func (_m *API) QueryInvoke(ctx context.Context, req *ffcapi.QueryInvokeRequest) return r0, r1, r2 } +// ReconcileConfirmationsForTransaction provides a mock function with given fields: ctx, txHash, confirmMap, targetConfirmationCount +func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount int) (*ffcapi.ConfirmationMapUpdateResult, error) { + ret := _m.Called(ctx, txHash, confirmMap, targetConfirmationCount) + + if len(ret) == 0 { + panic("no return value specified for ReconcileConfirmationsForTransaction") + } + + var r0 *ffcapi.ConfirmationMapUpdateResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *ffcapi.ConfirmationMap, int) (*ffcapi.ConfirmationMapUpdateResult, error)); ok { + return rf(ctx, txHash, confirmMap, targetConfirmationCount) + } + if rf, ok := ret.Get(0).(func(context.Context, string, *ffcapi.ConfirmationMap, int) *ffcapi.ConfirmationMapUpdateResult); ok { + r0 = rf(ctx, txHash, confirmMap, targetConfirmationCount) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ffcapi.ConfirmationMapUpdateResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, *ffcapi.ConfirmationMap, int) error); ok { + r1 = rf(ctx, txHash, confirmMap, targetConfirmationCount) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // TransactionPrepare provides a mock function with given fields: ctx, req func (_m *API) TransactionPrepare(ctx context.Context, req *ffcapi.TransactionPrepareRequest) (*ffcapi.TransactionPrepareResponse, ffcapi.ErrorReason, error) { ret := _m.Called(ctx, req) diff --git a/mocks/metricsmocks/event_metrics_emitter.go b/mocks/metricsmocks/event_metrics_emitter.go index 94c0cf19..eb92f91e 100644 --- a/mocks/metricsmocks/event_metrics_emitter.go +++ b/mocks/metricsmocks/event_metrics_emitter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package metricsmocks diff --git a/mocks/metricsmocks/transaction_handler_metrics.go b/mocks/metricsmocks/transaction_handler_metrics.go index a4102a7c..f6033653 100644 --- a/mocks/metricsmocks/transaction_handler_metrics.go +++ b/mocks/metricsmocks/transaction_handler_metrics.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package metricsmocks diff --git a/mocks/persistencemocks/persistence.go b/mocks/persistencemocks/persistence.go index 7ab9de96..740e89d6 100644 --- a/mocks/persistencemocks/persistence.go +++ b/mocks/persistencemocks/persistence.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package persistencemocks diff --git a/mocks/persistencemocks/rich_query.go b/mocks/persistencemocks/rich_query.go index 9253d685..5cd5f614 100644 --- a/mocks/persistencemocks/rich_query.go +++ b/mocks/persistencemocks/rich_query.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package persistencemocks diff --git a/mocks/persistencemocks/transaction_persistence.go b/mocks/persistencemocks/transaction_persistence.go index f25f0b4f..7cc7a5e6 100644 --- a/mocks/persistencemocks/transaction_persistence.go +++ b/mocks/persistencemocks/transaction_persistence.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package persistencemocks diff --git a/mocks/txhandlermocks/managed_tx_event_handler.go b/mocks/txhandlermocks/managed_tx_event_handler.go index 9206d4c3..0f1f2183 100644 --- a/mocks/txhandlermocks/managed_tx_event_handler.go +++ b/mocks/txhandlermocks/managed_tx_event_handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package txhandlermocks diff --git a/mocks/txhandlermocks/transaction_handler.go b/mocks/txhandlermocks/transaction_handler.go index 8b13bb46..7fbc1810 100644 --- a/mocks/txhandlermocks/transaction_handler.go +++ b/mocks/txhandlermocks/transaction_handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package txhandlermocks diff --git a/mocks/wsmocks/web_socket_channels.go b/mocks/wsmocks/web_socket_channels.go index c16d00f4..825c5799 100644 --- a/mocks/wsmocks/web_socket_channels.go +++ b/mocks/wsmocks/web_socket_channels.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package wsmocks diff --git a/mocks/wsmocks/web_socket_server.go b/mocks/wsmocks/web_socket_server.go index fdaf1d68..7bd01348 100644 --- a/mocks/wsmocks/web_socket_server.go +++ b/mocks/wsmocks/web_socket_server.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package wsmocks diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index 7b7c1489..edf811ad 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -85,6 +85,9 @@ type API interface { // NewBlockListener creates a new block listener, decoupled from an event stream NewBlockListener(ctx context.Context, req *NewBlockListenerRequest) (*NewBlockListenerResponse, ErrorReason, error) + // ReconcileConfirmationsForTransaction reconciles the confirmations for a transaction hash + ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ConfirmationMap, targetConfirmationCount int) (*ConfirmationMapUpdateResult, error) + // IsLive confirms if the connector up and running IsLive(ctx context.Context) (*LiveResponse, ErrorReason, error) @@ -92,6 +95,38 @@ type API interface { IsReady(ctx context.Context) (*ReadyResponse, ErrorReason, error) } +type ConfirmationMapUpdateResult struct { + *ConfirmationMap + HasNewFork bool `json:"hasNewFork,omitempty"` // when set to true, it means a fork is detected based on the existing confirmations + Rebuilt bool `json:"rebuilt,omitempty"` // when set to true, it means all of the existing confirmations are discarded + HasNewConfirmation bool `json:"hasNewConfirmation,omitempty"` // when set to true, it means new blocks from canonical chain are added to the confirmation queue + Confirmed bool `json:"confirmed,omitempty"` // when set to true, it means the confirmation queue is complete and all the blocks are confirmed + TargetConfirmationCount int `json:"targetConfirmationCount"` // the target number of confirmations for this event +} + +type ConfirmationMap struct { + // confirmation map is contains a list of possible confirmations for a transaction + // the key is the hash of the first block that contains the transaction hash + // the first block is the block that contains the transaction hash + ConfirmationQueueMap map[string][]*Confirmation `json:"confirmationQueueMap,omitempty"` + // which block hash that leads a confirmation queue matches the canonical block hash + CanonicalBlockHash string `json:"canonicalBlockHash,omitempty"` +} + +type Confirmation struct { // duplicate of apitypes.Confirmation due to circular dependency + BlockNumber fftypes.FFuint64 `json:"blockNumber"` + BlockHash string `json:"blockHash"` + ParentHash string `json:"parentHash"` +} + +func (c *Confirmation) Equal(other *Confirmation) bool { + return c.BlockNumber == other.BlockNumber && c.BlockHash == other.BlockHash && c.ParentHash == other.ParentHash +} + +func (c *Confirmation) IsParentOf(other *Confirmation) bool { + return c.BlockHash == other.ParentHash && c.BlockNumber+1 == other.BlockNumber +} + type BlockHashEvent struct { BlockHashes []string `json:"blockHash"` // zero or more hashes (can be nil) GapPotential bool `json:"gapPotential,omitempty"` // when true, the caller cannot be sure if blocks have been missed (use on reconnect of a websocket for example) diff --git a/pkg/fftm/manager.go b/pkg/fftm/manager.go index 27b73c2e..e247436e 100644 --- a/pkg/fftm/manager.go +++ b/pkg/fftm/manager.go @@ -73,6 +73,10 @@ type Manager interface { // Ability to query a transaction by ID to get full status GetTransactionByIDWithStatus(ctx context.Context, txID string, withHistory bool) (transaction *apitypes.TXWithStatus, err error) + // Ability to reconcile confirmations for a transaction + // This function uses the single in-memory canonical chain to check and build the confirmation map of a given transaction hash + ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount int) (*ffcapi.ConfirmationMapUpdateResult, error) + // Ability to submit new transactions into the transaction handler for management/submission TransactionHandler() txhandler.TransactionHandler } diff --git a/pkg/fftm/transaction_management.go b/pkg/fftm/transaction_management.go index 50a409ad..ac529a6d 100644 --- a/pkg/fftm/transaction_management.go +++ b/pkg/fftm/transaction_management.go @@ -25,9 +25,14 @@ import ( "github.com/hyperledger/firefly-common/pkg/i18n" "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs" "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes" + "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi" "github.com/hyperledger/firefly-transaction-manager/pkg/txhandler" ) +func (m *manager) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount int) (*ffcapi.ConfirmationMapUpdateResult, error) { + return m.connector.ReconcileConfirmationsForTransaction(ctx, txHash, confirmMap, targetConfirmationCount) +} + func (m *manager) GetTransactionByIDWithStatus(ctx context.Context, txID string, withHistory bool) (transaction *apitypes.TXWithStatus, err error) { tx, err := m.persistence.GetTransactionByIDWithStatus(ctx, txID, withHistory) if err != nil { diff --git a/pkg/fftm/transaction_management_test.go b/pkg/fftm/transaction_management_test.go index 4069f183..c665f9df 100644 --- a/pkg/fftm/transaction_management_test.go +++ b/pkg/fftm/transaction_management_test.go @@ -21,12 +21,33 @@ import ( "net/http" "testing" + "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks" "github.com/hyperledger/firefly-transaction-manager/mocks/persistencemocks" "github.com/hyperledger/firefly-transaction-manager/mocks/txhandlermocks" + "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) +func TestReconcileConfirmationsForTransaction(t *testing.T) { + _, m, done := newTestManager(t) + defer done() + mFFC := m.connector.(*ffcapimocks.API) + + mFFC.On("ReconcileConfirmationsForTransaction", m.ctx, "0x1234567890", &ffcapi.ConfirmationMap{ + ConfirmationQueueMap: make(map[string][]*ffcapi.Confirmation), + }, 1).Return(&ffcapi.ConfirmationMapUpdateResult{ + ConfirmationMap: &ffcapi.ConfirmationMap{ + ConfirmationQueueMap: make(map[string][]*ffcapi.Confirmation), + }, + }, nil) + + _, err := m.ReconcileConfirmationsForTransaction(m.ctx, "0x1234567890", &ffcapi.ConfirmationMap{ + ConfirmationQueueMap: make(map[string][]*ffcapi.Confirmation), + }, 1) + assert.NoError(t, err) +} + func TestGetTransactionErrors(t *testing.T) { _, m, close := newTestManagerMockPersistence(t) From 07127ff35b095d5a0fa457cbe8998b2eb280b2be Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 10 Sep 2025 16:32:51 +0100 Subject: [PATCH 02/12] rename confirmatino to minimal block info Signed-off-by: Chengxuan Xing --- pkg/ffcapi/api.go | 18 +++++++++--------- pkg/fftm/transaction_management_test.go | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index edf811ad..74a08214 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -97,33 +97,33 @@ type API interface { type ConfirmationMapUpdateResult struct { *ConfirmationMap - HasNewFork bool `json:"hasNewFork,omitempty"` // when set to true, it means a fork is detected based on the existing confirmations - Rebuilt bool `json:"rebuilt,omitempty"` // when set to true, it means all of the existing confirmations are discarded - HasNewConfirmation bool `json:"hasNewConfirmation,omitempty"` // when set to true, it means new blocks from canonical chain are added to the confirmation queue - Confirmed bool `json:"confirmed,omitempty"` // when set to true, it means the confirmation queue is complete and all the blocks are confirmed - TargetConfirmationCount int `json:"targetConfirmationCount"` // the target number of confirmations for this event + HasNewFork bool `json:"hasNewFork,omitempty"` // when set to true, it means a fork is detected based on the existing confirmations + Rebuilt bool `json:"rebuilt,omitempty"` // when set to true, it means all of the existing confirmations are discarded + HasNewConfirmation bool `json:"hasNewConfirmation,omitempty"` // when set to true, it means new blocks from canonical chain are added to the confirmation queue + Confirmed bool `json:"confirmed,omitempty"` // when set to true, it means the confirmation queue is complete and all the blocks are confirmed + TargetConfirmationCount fftypes.FFuint64 `json:"targetConfirmationCount"` // the target number of confirmations for this event } type ConfirmationMap struct { // confirmation map is contains a list of possible confirmations for a transaction // the key is the hash of the first block that contains the transaction hash // the first block is the block that contains the transaction hash - ConfirmationQueueMap map[string][]*Confirmation `json:"confirmationQueueMap,omitempty"` + ConfirmationQueueMap map[string][]*MinimalBlockInfo `json:"confirmationQueueMap,omitempty"` // which block hash that leads a confirmation queue matches the canonical block hash CanonicalBlockHash string `json:"canonicalBlockHash,omitempty"` } -type Confirmation struct { // duplicate of apitypes.Confirmation due to circular dependency +type MinimalBlockInfo struct { // duplicate of apitypes.Confirmation due to circular dependency BlockNumber fftypes.FFuint64 `json:"blockNumber"` BlockHash string `json:"blockHash"` ParentHash string `json:"parentHash"` } -func (c *Confirmation) Equal(other *Confirmation) bool { +func (c *MinimalBlockInfo) Equal(other *MinimalBlockInfo) bool { return c.BlockNumber == other.BlockNumber && c.BlockHash == other.BlockHash && c.ParentHash == other.ParentHash } -func (c *Confirmation) IsParentOf(other *Confirmation) bool { +func (c *MinimalBlockInfo) IsParentOf(other *MinimalBlockInfo) bool { return c.BlockHash == other.ParentHash && c.BlockNumber+1 == other.BlockNumber } diff --git a/pkg/fftm/transaction_management_test.go b/pkg/fftm/transaction_management_test.go index c665f9df..a4f4d185 100644 --- a/pkg/fftm/transaction_management_test.go +++ b/pkg/fftm/transaction_management_test.go @@ -35,15 +35,15 @@ func TestReconcileConfirmationsForTransaction(t *testing.T) { mFFC := m.connector.(*ffcapimocks.API) mFFC.On("ReconcileConfirmationsForTransaction", m.ctx, "0x1234567890", &ffcapi.ConfirmationMap{ - ConfirmationQueueMap: make(map[string][]*ffcapi.Confirmation), + ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), }, 1).Return(&ffcapi.ConfirmationMapUpdateResult{ ConfirmationMap: &ffcapi.ConfirmationMap{ - ConfirmationQueueMap: make(map[string][]*ffcapi.Confirmation), + ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), }, }, nil) _, err := m.ReconcileConfirmationsForTransaction(m.ctx, "0x1234567890", &ffcapi.ConfirmationMap{ - ConfirmationQueueMap: make(map[string][]*ffcapi.Confirmation), + ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), }, 1) assert.NoError(t, err) } From 14142cf9f69765be727882fa2c3cc049a95b5181 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 10 Sep 2025 16:35:33 +0100 Subject: [PATCH 03/12] fixing function signature Signed-off-by: Chengxuan Xing --- mocks/ffcapimocks/api.go | 8 ++++---- pkg/ffcapi/api.go | 12 ++++++------ pkg/fftm/manager.go | 2 +- pkg/fftm/transaction_management.go | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mocks/ffcapimocks/api.go b/mocks/ffcapimocks/api.go index f8451d9f..40daacbc 100644 --- a/mocks/ffcapimocks/api.go +++ b/mocks/ffcapimocks/api.go @@ -664,7 +664,7 @@ func (_m *API) QueryInvoke(ctx context.Context, req *ffcapi.QueryInvokeRequest) } // ReconcileConfirmationsForTransaction provides a mock function with given fields: ctx, txHash, confirmMap, targetConfirmationCount -func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount int) (*ffcapi.ConfirmationMapUpdateResult, error) { +func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) { ret := _m.Called(ctx, txHash, confirmMap, targetConfirmationCount) if len(ret) == 0 { @@ -673,10 +673,10 @@ func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash var r0 *ffcapi.ConfirmationMapUpdateResult var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, *ffcapi.ConfirmationMap, int) (*ffcapi.ConfirmationMapUpdateResult, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, *ffcapi.ConfirmationMap, uint64) (*ffcapi.ConfirmationMapUpdateResult, error)); ok { return rf(ctx, txHash, confirmMap, targetConfirmationCount) } - if rf, ok := ret.Get(0).(func(context.Context, string, *ffcapi.ConfirmationMap, int) *ffcapi.ConfirmationMapUpdateResult); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, *ffcapi.ConfirmationMap, uint64) *ffcapi.ConfirmationMapUpdateResult); ok { r0 = rf(ctx, txHash, confirmMap, targetConfirmationCount) } else { if ret.Get(0) != nil { @@ -684,7 +684,7 @@ func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash } } - if rf, ok := ret.Get(1).(func(context.Context, string, *ffcapi.ConfirmationMap, int) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string, *ffcapi.ConfirmationMap, uint64) error); ok { r1 = rf(ctx, txHash, confirmMap, targetConfirmationCount) } else { r1 = ret.Error(1) diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index 74a08214..64c553ad 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -86,7 +86,7 @@ type API interface { NewBlockListener(ctx context.Context, req *NewBlockListenerRequest) (*NewBlockListenerResponse, ErrorReason, error) // ReconcileConfirmationsForTransaction reconciles the confirmations for a transaction hash - ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ConfirmationMap, targetConfirmationCount int) (*ConfirmationMapUpdateResult, error) + ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ConfirmationMap, targetConfirmationCount uint64) (*ConfirmationMapUpdateResult, error) // IsLive confirms if the connector up and running IsLive(ctx context.Context) (*LiveResponse, ErrorReason, error) @@ -97,11 +97,11 @@ type API interface { type ConfirmationMapUpdateResult struct { *ConfirmationMap - HasNewFork bool `json:"hasNewFork,omitempty"` // when set to true, it means a fork is detected based on the existing confirmations - Rebuilt bool `json:"rebuilt,omitempty"` // when set to true, it means all of the existing confirmations are discarded - HasNewConfirmation bool `json:"hasNewConfirmation,omitempty"` // when set to true, it means new blocks from canonical chain are added to the confirmation queue - Confirmed bool `json:"confirmed,omitempty"` // when set to true, it means the confirmation queue is complete and all the blocks are confirmed - TargetConfirmationCount fftypes.FFuint64 `json:"targetConfirmationCount"` // the target number of confirmations for this event + HasNewFork bool `json:"hasNewFork,omitempty"` // when set to true, it means a fork is detected based on the existing confirmations + Rebuilt bool `json:"rebuilt,omitempty"` // when set to true, it means all of the existing confirmations are discarded + HasNewConfirmation bool `json:"hasNewConfirmation,omitempty"` // when set to true, it means new blocks from canonical chain are added to the confirmation queue + Confirmed bool `json:"confirmed,omitempty"` // when set to true, it means the confirmation queue is complete and all the blocks are confirmed + TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this event } type ConfirmationMap struct { diff --git a/pkg/fftm/manager.go b/pkg/fftm/manager.go index e247436e..93ece45e 100644 --- a/pkg/fftm/manager.go +++ b/pkg/fftm/manager.go @@ -75,7 +75,7 @@ type Manager interface { // Ability to reconcile confirmations for a transaction // This function uses the single in-memory canonical chain to check and build the confirmation map of a given transaction hash - ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount int) (*ffcapi.ConfirmationMapUpdateResult, error) + ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) // Ability to submit new transactions into the transaction handler for management/submission TransactionHandler() txhandler.TransactionHandler diff --git a/pkg/fftm/transaction_management.go b/pkg/fftm/transaction_management.go index ac529a6d..367d716f 100644 --- a/pkg/fftm/transaction_management.go +++ b/pkg/fftm/transaction_management.go @@ -29,7 +29,7 @@ import ( "github.com/hyperledger/firefly-transaction-manager/pkg/txhandler" ) -func (m *manager) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount int) (*ffcapi.ConfirmationMapUpdateResult, error) { +func (m *manager) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) { return m.connector.ReconcileConfirmationsForTransaction(ctx, txHash, confirmMap, targetConfirmationCount) } From e6bcd228c37508c997d791107a09255da2865454 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 10 Sep 2025 16:51:25 +0100 Subject: [PATCH 04/12] fixing test Signed-off-by: Chengxuan Xing --- pkg/fftm/transaction_management_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/fftm/transaction_management_test.go b/pkg/fftm/transaction_management_test.go index a4f4d185..b6657e67 100644 --- a/pkg/fftm/transaction_management_test.go +++ b/pkg/fftm/transaction_management_test.go @@ -36,7 +36,7 @@ func TestReconcileConfirmationsForTransaction(t *testing.T) { mFFC.On("ReconcileConfirmationsForTransaction", m.ctx, "0x1234567890", &ffcapi.ConfirmationMap{ ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), - }, 1).Return(&ffcapi.ConfirmationMapUpdateResult{ + }, uint64(1)).Return(&ffcapi.ConfirmationMapUpdateResult{ ConfirmationMap: &ffcapi.ConfirmationMap{ ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), }, @@ -44,7 +44,7 @@ func TestReconcileConfirmationsForTransaction(t *testing.T) { _, err := m.ReconcileConfirmationsForTransaction(m.ctx, "0x1234567890", &ffcapi.ConfirmationMap{ ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), - }, 1) + }, uint64(1)) assert.NoError(t, err) } From e8c5273ca90c479fbae0079fdb915481c55734e1 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 11 Sep 2025 12:55:37 +0100 Subject: [PATCH 05/12] udpate description Signed-off-by: Chengxuan Xing --- pkg/ffcapi/api.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index 64c553ad..0617459c 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -105,11 +105,15 @@ type ConfirmationMapUpdateResult struct { } type ConfirmationMap struct { - // confirmation map is contains a list of possible confirmations for a transaction - // the key is the hash of the first block that contains the transaction hash - // the first block is the block that contains the transaction hash + // confirmation map maintains a list of possible confirmations for a transaction + // the key of the map is the hash of the first block (tx block) that contains the transaction hash + // the value of the map is an array of blocks, the first block is the tx block + // the rest of the blocks are blocks inside the range of the target confirmation count + // gap is allowed between the tx block and the second block + // no gaps are allowed after the second block + // the second block can be outside the target confirmation count when it is the last block in the confirmation queue ConfirmationQueueMap map[string][]*MinimalBlockInfo `json:"confirmationQueueMap,omitempty"` - // which block hash that leads a confirmation queue matches the canonical block hash + // the tx block hash that is on the current in-memory canonical chain CanonicalBlockHash string `json:"canonicalBlockHash,omitempty"` } From 18bc46221abb448bc3fb100d03c74747638ebf28 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Mon, 15 Sep 2025 13:46:13 +0100 Subject: [PATCH 06/12] Update pkg/ffcapi/api.go Signed-off-by: Chengxuan Xing --- pkg/ffcapi/api.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index 0617459c..eade0101 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -107,9 +107,7 @@ type ConfirmationMapUpdateResult struct { type ConfirmationMap struct { // confirmation map maintains a list of possible confirmations for a transaction // the key of the map is the hash of the first block (tx block) that contains the transaction hash - // the value of the map is an array of blocks, the first block is the tx block - // the rest of the blocks are blocks inside the range of the target confirmation count - // gap is allowed between the tx block and the second block + // the value of the map is an array of blocks // no gaps are allowed after the second block // the second block can be outside the target confirmation count when it is the last block in the confirmation queue ConfirmationQueueMap map[string][]*MinimalBlockInfo `json:"confirmationQueueMap,omitempty"` From a1e02b75dbc9d76fa3b94364ef2a7758f1d11c17 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Tue, 30 Sep 2025 12:39:38 +0100 Subject: [PATCH 07/12] update confirmation object based on review comments Signed-off-by: Chengxuan Xing --- mocks/ffcapimocks/api.go | 18 ++++++++-------- pkg/ffcapi/api.go | 28 ++++++++----------------- pkg/fftm/manager.go | 2 +- pkg/fftm/transaction_management.go | 4 ++-- pkg/fftm/transaction_management_test.go | 12 +++-------- 5 files changed, 24 insertions(+), 40 deletions(-) diff --git a/mocks/ffcapimocks/api.go b/mocks/ffcapimocks/api.go index 40daacbc..61e851bb 100644 --- a/mocks/ffcapimocks/api.go +++ b/mocks/ffcapimocks/api.go @@ -663,9 +663,9 @@ func (_m *API) QueryInvoke(ctx context.Context, req *ffcapi.QueryInvokeRequest) return r0, r1, r2 } -// ReconcileConfirmationsForTransaction provides a mock function with given fields: ctx, txHash, confirmMap, targetConfirmationCount -func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) { - ret := _m.Called(ctx, txHash, confirmMap, targetConfirmationCount) +// ReconcileConfirmationsForTransaction provides a mock function with given fields: ctx, txHash, existingConfirmations, targetConfirmationCount +func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) { + ret := _m.Called(ctx, txHash, existingConfirmations, targetConfirmationCount) if len(ret) == 0 { panic("no return value specified for ReconcileConfirmationsForTransaction") @@ -673,19 +673,19 @@ func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash var r0 *ffcapi.ConfirmationMapUpdateResult var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, *ffcapi.ConfirmationMap, uint64) (*ffcapi.ConfirmationMapUpdateResult, error)); ok { - return rf(ctx, txHash, confirmMap, targetConfirmationCount) + if rf, ok := ret.Get(0).(func(context.Context, string, []*ffcapi.MinimalBlockInfo, uint64) (*ffcapi.ConfirmationMapUpdateResult, error)); ok { + return rf(ctx, txHash, existingConfirmations, targetConfirmationCount) } - if rf, ok := ret.Get(0).(func(context.Context, string, *ffcapi.ConfirmationMap, uint64) *ffcapi.ConfirmationMapUpdateResult); ok { - r0 = rf(ctx, txHash, confirmMap, targetConfirmationCount) + if rf, ok := ret.Get(0).(func(context.Context, string, []*ffcapi.MinimalBlockInfo, uint64) *ffcapi.ConfirmationMapUpdateResult); ok { + r0 = rf(ctx, txHash, existingConfirmations, targetConfirmationCount) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*ffcapi.ConfirmationMapUpdateResult) } } - if rf, ok := ret.Get(1).(func(context.Context, string, *ffcapi.ConfirmationMap, uint64) error); ok { - r1 = rf(ctx, txHash, confirmMap, targetConfirmationCount) + if rf, ok := ret.Get(1).(func(context.Context, string, []*ffcapi.MinimalBlockInfo, uint64) error); ok { + r1 = rf(ctx, txHash, existingConfirmations, targetConfirmationCount) } else { r1 = ret.Error(1) } diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index eade0101..e336b2f3 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -86,7 +86,7 @@ type API interface { NewBlockListener(ctx context.Context, req *NewBlockListenerRequest) (*NewBlockListenerResponse, ErrorReason, error) // ReconcileConfirmationsForTransaction reconciles the confirmations for a transaction hash - ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ConfirmationMap, targetConfirmationCount uint64) (*ConfirmationMapUpdateResult, error) + ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*MinimalBlockInfo, targetConfirmationCount uint64) (*ConfirmationMapUpdateResult, error) // IsLive confirms if the connector up and running IsLive(ctx context.Context) (*LiveResponse, ErrorReason, error) @@ -96,25 +96,15 @@ type API interface { } type ConfirmationMapUpdateResult struct { - *ConfirmationMap - HasNewFork bool `json:"hasNewFork,omitempty"` // when set to true, it means a fork is detected based on the existing confirmations - Rebuilt bool `json:"rebuilt,omitempty"` // when set to true, it means all of the existing confirmations are discarded - HasNewConfirmation bool `json:"hasNewConfirmation,omitempty"` // when set to true, it means new blocks from canonical chain are added to the confirmation queue - Confirmed bool `json:"confirmed,omitempty"` // when set to true, it means the confirmation queue is complete and all the blocks are confirmed - TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this event + // confirmation map maintains a list of confirmed blocks for a transaction + // the first block is the block that contains the transaction hash + Confirmations []*MinimalBlockInfo `json:"confirmations,omitempty"` + HasNewFork bool `json:"hasNewFork,omitempty"` // when set to true, it means a fork is detected based on the existing confirmations + Rebuilt bool `json:"rebuilt,omitempty"` // when set to true, it means all of the existing confirmations are discarded + HasNewConfirmation bool `json:"hasNewConfirmation,omitempty"` // when set to true, it means new blocks from canonical chain are added to the confirmation queue + Confirmed bool `json:"confirmed,omitempty"` // when set to true, it means the confirmation queue is complete and all the blocks are confirmed + TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this event } - -type ConfirmationMap struct { - // confirmation map maintains a list of possible confirmations for a transaction - // the key of the map is the hash of the first block (tx block) that contains the transaction hash - // the value of the map is an array of blocks - // no gaps are allowed after the second block - // the second block can be outside the target confirmation count when it is the last block in the confirmation queue - ConfirmationQueueMap map[string][]*MinimalBlockInfo `json:"confirmationQueueMap,omitempty"` - // the tx block hash that is on the current in-memory canonical chain - CanonicalBlockHash string `json:"canonicalBlockHash,omitempty"` -} - type MinimalBlockInfo struct { // duplicate of apitypes.Confirmation due to circular dependency BlockNumber fftypes.FFuint64 `json:"blockNumber"` BlockHash string `json:"blockHash"` diff --git a/pkg/fftm/manager.go b/pkg/fftm/manager.go index 93ece45e..79fc5b46 100644 --- a/pkg/fftm/manager.go +++ b/pkg/fftm/manager.go @@ -75,7 +75,7 @@ type Manager interface { // Ability to reconcile confirmations for a transaction // This function uses the single in-memory canonical chain to check and build the confirmation map of a given transaction hash - ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) + ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) // Ability to submit new transactions into the transaction handler for management/submission TransactionHandler() txhandler.TransactionHandler diff --git a/pkg/fftm/transaction_management.go b/pkg/fftm/transaction_management.go index 367d716f..20b95d00 100644 --- a/pkg/fftm/transaction_management.go +++ b/pkg/fftm/transaction_management.go @@ -29,8 +29,8 @@ import ( "github.com/hyperledger/firefly-transaction-manager/pkg/txhandler" ) -func (m *manager) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, confirmMap *ffcapi.ConfirmationMap, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) { - return m.connector.ReconcileConfirmationsForTransaction(ctx, txHash, confirmMap, targetConfirmationCount) +func (m *manager) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) { + return m.connector.ReconcileConfirmationsForTransaction(ctx, txHash, existingConfirmations, targetConfirmationCount) } func (m *manager) GetTransactionByIDWithStatus(ctx context.Context, txID string, withHistory bool) (transaction *apitypes.TXWithStatus, err error) { diff --git a/pkg/fftm/transaction_management_test.go b/pkg/fftm/transaction_management_test.go index b6657e67..5852236d 100644 --- a/pkg/fftm/transaction_management_test.go +++ b/pkg/fftm/transaction_management_test.go @@ -34,17 +34,11 @@ func TestReconcileConfirmationsForTransaction(t *testing.T) { defer done() mFFC := m.connector.(*ffcapimocks.API) - mFFC.On("ReconcileConfirmationsForTransaction", m.ctx, "0x1234567890", &ffcapi.ConfirmationMap{ - ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), - }, uint64(1)).Return(&ffcapi.ConfirmationMapUpdateResult{ - ConfirmationMap: &ffcapi.ConfirmationMap{ - ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), - }, + mFFC.On("ReconcileConfirmationsForTransaction", m.ctx, "0x1234567890", []*ffcapi.MinimalBlockInfo{}, uint64(1)).Return(&ffcapi.ConfirmationMapUpdateResult{ + Confirmations: []*ffcapi.MinimalBlockInfo{}, }, nil) - _, err := m.ReconcileConfirmationsForTransaction(m.ctx, "0x1234567890", &ffcapi.ConfirmationMap{ - ConfirmationQueueMap: make(map[string][]*ffcapi.MinimalBlockInfo), - }, uint64(1)) + _, err := m.ReconcileConfirmationsForTransaction(m.ctx, "0x1234567890", []*ffcapi.MinimalBlockInfo{}, uint64(1)) assert.NoError(t, err) } From 46c9271ca66e0c1be15acde64903aa679673489f Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 3 Oct 2025 12:31:49 +0100 Subject: [PATCH 08/12] remove attributes that are hard to calculate Signed-off-by: Chengxuan Xing --- pkg/ffcapi/api.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index e336b2f3..755b4564 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -99,11 +99,9 @@ type ConfirmationMapUpdateResult struct { // confirmation map maintains a list of confirmed blocks for a transaction // the first block is the block that contains the transaction hash Confirmations []*MinimalBlockInfo `json:"confirmations,omitempty"` - HasNewFork bool `json:"hasNewFork,omitempty"` // when set to true, it means a fork is detected based on the existing confirmations - Rebuilt bool `json:"rebuilt,omitempty"` // when set to true, it means all of the existing confirmations are discarded - HasNewConfirmation bool `json:"hasNewConfirmation,omitempty"` // when set to true, it means new blocks from canonical chain are added to the confirmation queue - Confirmed bool `json:"confirmed,omitempty"` // when set to true, it means the confirmation queue is complete and all the blocks are confirmed - TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this event + NewFork bool `json:"newFork,omitempty"` // when true, it means a fork is detected based on the existing confirmations + Confirmed bool `json:"confirmed,omitempty"` // when true, it means the confirmation queue is complete and all the blocks are confirmed + TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this event } type MinimalBlockInfo struct { // duplicate of apitypes.Confirmation due to circular dependency BlockNumber fftypes.FFuint64 `json:"blockNumber"` From cc15eea20e9724b88922902be9a0e60d1a25c30b Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 3 Oct 2025 16:20:28 +0100 Subject: [PATCH 09/12] Apply suggestions from code review Signed-off-by: Chengxuan Xing --- pkg/ffcapi/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index 755b4564..a7c20c01 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -101,7 +101,7 @@ type ConfirmationMapUpdateResult struct { Confirmations []*MinimalBlockInfo `json:"confirmations,omitempty"` NewFork bool `json:"newFork,omitempty"` // when true, it means a fork is detected based on the existing confirmations Confirmed bool `json:"confirmed,omitempty"` // when true, it means the confirmation queue is complete and all the blocks are confirmed - TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this event + TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this reconcile request } type MinimalBlockInfo struct { // duplicate of apitypes.Confirmation due to circular dependency BlockNumber fftypes.FFuint64 `json:"blockNumber"` From d6f944cab6b614ad4edd2773aad0e98eb17017d0 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 17 Oct 2025 16:31:49 +0100 Subject: [PATCH 10/12] rename Signed-off-by: Chengxuan Xing --- mocks/ffcapimocks/api.go | 10 +++++----- pkg/ffcapi/api.go | 6 +++--- pkg/fftm/manager.go | 2 +- pkg/fftm/transaction_management.go | 2 +- pkg/fftm/transaction_management_test.go | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mocks/ffcapimocks/api.go b/mocks/ffcapimocks/api.go index 61e851bb..c352b099 100644 --- a/mocks/ffcapimocks/api.go +++ b/mocks/ffcapimocks/api.go @@ -664,23 +664,23 @@ func (_m *API) QueryInvoke(ctx context.Context, req *ffcapi.QueryInvokeRequest) } // ReconcileConfirmationsForTransaction provides a mock function with given fields: ctx, txHash, existingConfirmations, targetConfirmationCount -func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) { +func (_m *API) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationUpdateResult, error) { ret := _m.Called(ctx, txHash, existingConfirmations, targetConfirmationCount) if len(ret) == 0 { panic("no return value specified for ReconcileConfirmationsForTransaction") } - var r0 *ffcapi.ConfirmationMapUpdateResult + var r0 *ffcapi.ConfirmationUpdateResult var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, []*ffcapi.MinimalBlockInfo, uint64) (*ffcapi.ConfirmationMapUpdateResult, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, []*ffcapi.MinimalBlockInfo, uint64) (*ffcapi.ConfirmationUpdateResult, error)); ok { return rf(ctx, txHash, existingConfirmations, targetConfirmationCount) } - if rf, ok := ret.Get(0).(func(context.Context, string, []*ffcapi.MinimalBlockInfo, uint64) *ffcapi.ConfirmationMapUpdateResult); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, []*ffcapi.MinimalBlockInfo, uint64) *ffcapi.ConfirmationUpdateResult); ok { r0 = rf(ctx, txHash, existingConfirmations, targetConfirmationCount) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*ffcapi.ConfirmationMapUpdateResult) + r0 = ret.Get(0).(*ffcapi.ConfirmationUpdateResult) } } diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index a7c20c01..74b6c9ff 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -86,7 +86,7 @@ type API interface { NewBlockListener(ctx context.Context, req *NewBlockListenerRequest) (*NewBlockListenerResponse, ErrorReason, error) // ReconcileConfirmationsForTransaction reconciles the confirmations for a transaction hash - ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*MinimalBlockInfo, targetConfirmationCount uint64) (*ConfirmationMapUpdateResult, error) + ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*MinimalBlockInfo, targetConfirmationCount uint64) (*ConfirmationUpdateResult, error) // IsLive confirms if the connector up and running IsLive(ctx context.Context) (*LiveResponse, ErrorReason, error) @@ -95,8 +95,8 @@ type API interface { IsReady(ctx context.Context) (*ReadyResponse, ErrorReason, error) } -type ConfirmationMapUpdateResult struct { - // confirmation map maintains a list of confirmed blocks for a transaction +type ConfirmationUpdateResult struct { + // confirmation queue has a list of confirmed blocks for a transaction // the first block is the block that contains the transaction hash Confirmations []*MinimalBlockInfo `json:"confirmations,omitempty"` NewFork bool `json:"newFork,omitempty"` // when true, it means a fork is detected based on the existing confirmations diff --git a/pkg/fftm/manager.go b/pkg/fftm/manager.go index 79fc5b46..120310c3 100644 --- a/pkg/fftm/manager.go +++ b/pkg/fftm/manager.go @@ -75,7 +75,7 @@ type Manager interface { // Ability to reconcile confirmations for a transaction // This function uses the single in-memory canonical chain to check and build the confirmation map of a given transaction hash - ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) + ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationUpdateResult, error) // Ability to submit new transactions into the transaction handler for management/submission TransactionHandler() txhandler.TransactionHandler diff --git a/pkg/fftm/transaction_management.go b/pkg/fftm/transaction_management.go index 20b95d00..1084edb1 100644 --- a/pkg/fftm/transaction_management.go +++ b/pkg/fftm/transaction_management.go @@ -29,7 +29,7 @@ import ( "github.com/hyperledger/firefly-transaction-manager/pkg/txhandler" ) -func (m *manager) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationMapUpdateResult, error) { +func (m *manager) ReconcileConfirmationsForTransaction(ctx context.Context, txHash string, existingConfirmations []*ffcapi.MinimalBlockInfo, targetConfirmationCount uint64) (*ffcapi.ConfirmationUpdateResult, error) { return m.connector.ReconcileConfirmationsForTransaction(ctx, txHash, existingConfirmations, targetConfirmationCount) } diff --git a/pkg/fftm/transaction_management_test.go b/pkg/fftm/transaction_management_test.go index 5852236d..ef3dd323 100644 --- a/pkg/fftm/transaction_management_test.go +++ b/pkg/fftm/transaction_management_test.go @@ -34,7 +34,7 @@ func TestReconcileConfirmationsForTransaction(t *testing.T) { defer done() mFFC := m.connector.(*ffcapimocks.API) - mFFC.On("ReconcileConfirmationsForTransaction", m.ctx, "0x1234567890", []*ffcapi.MinimalBlockInfo{}, uint64(1)).Return(&ffcapi.ConfirmationMapUpdateResult{ + mFFC.On("ReconcileConfirmationsForTransaction", m.ctx, "0x1234567890", []*ffcapi.MinimalBlockInfo{}, uint64(1)).Return(&ffcapi.ConfirmationUpdateResult{ Confirmations: []*ffcapi.MinimalBlockInfo{}, }, nil) From 8e8e3629f7fa5439257a9a1f71b9d96f01971996 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 24 Oct 2025 18:41:18 +0100 Subject: [PATCH 11/12] add back rebuilt flag Signed-off-by: Chengxuan Xing --- pkg/ffcapi/api.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index 74b6c9ff..b7162c9c 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -96,11 +96,18 @@ type API interface { } type ConfirmationUpdateResult struct { - // confirmation queue has a list of confirmed blocks for a transaction - // the first block is the block that contains the transaction hash + // a linked list of accumulated confirmations for a transaction + // the list is sorted by block number + // - the first block is the block that contains the transaction hash + // - the last block is the most recent confirmation + // this list can be used as input to the future reconcile request to avoid re-fetching the blocks if they are no longer + // in the in-memory partial chain + // WARNING: mutation to this list is not expected, invalid modifications will cause inefficiencies in the reconciliation process + // `rebuilt` will be true if an invalid confirmation list is detected by the reconciliation process Confirmations []*MinimalBlockInfo `json:"confirmations,omitempty"` - NewFork bool `json:"newFork,omitempty"` // when true, it means a fork is detected based on the existing confirmations - Confirmed bool `json:"confirmed,omitempty"` // when true, it means the confirmation queue is complete and all the blocks are confirmed + Rebuilt bool `json:"rebuilt,omitempty"` // when true, it means the existing confirmations contained invalid blocks, the new confirmations are rebuilt from scratch + NewFork bool `json:"newFork,omitempty"` // when true, it means a new fork was detected based on the existing confirmations, this will always be false if `rebuilt` is true + Confirmed bool `json:"confirmed,omitempty"` // when true, it means the confirmation list is complete and the transaction is confirmed TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this reconcile request } type MinimalBlockInfo struct { // duplicate of apitypes.Confirmation due to circular dependency From e01a231d8f2e92bc48d852d1ff2c144e03eba27a Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 24 Oct 2025 19:06:37 +0100 Subject: [PATCH 12/12] update comment Signed-off-by: Chengxuan Xing --- pkg/ffcapi/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ffcapi/api.go b/pkg/ffcapi/api.go index b7162c9c..921a9f37 100644 --- a/pkg/ffcapi/api.go +++ b/pkg/ffcapi/api.go @@ -106,7 +106,7 @@ type ConfirmationUpdateResult struct { // `rebuilt` will be true if an invalid confirmation list is detected by the reconciliation process Confirmations []*MinimalBlockInfo `json:"confirmations,omitempty"` Rebuilt bool `json:"rebuilt,omitempty"` // when true, it means the existing confirmations contained invalid blocks, the new confirmations are rebuilt from scratch - NewFork bool `json:"newFork,omitempty"` // when true, it means a new fork was detected based on the existing confirmations, this will always be false if `rebuilt` is true + NewFork bool `json:"newFork,omitempty"` // when true, it means a new fork was detected based on the existing confirmations Confirmed bool `json:"confirmed,omitempty"` // when true, it means the confirmation list is complete and the transaction is confirmed TargetConfirmationCount uint64 `json:"targetConfirmationCount"` // the target number of confirmations for this reconcile request }