From b72f27fbd3105eac4f9efa0e96271a09fc87947b Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Fri, 9 Aug 2024 12:51:38 -0700 Subject: [PATCH 1/5] wallet: use coreutils wallet types --- go.mod | 4 +- go.sum | 2 - wallet/events.go | 134 ------------------------------------------ wallet/wallet.go | 58 ++++++++++++++---- wallet/wallet_test.go | 48 ++------------- 5 files changed, 54 insertions(+), 192 deletions(-) delete mode 100644 wallet/events.go diff --git a/go.mod b/go.mod index df040fb..8ce388c 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,12 @@ go 1.21.8 toolchain go1.22.3 +replace go.sia.tech/coreutils => ../coreutils + require ( github.com/mattn/go-sqlite3 v1.14.22 go.sia.tech/core v0.4.2 - go.sia.tech/coreutils v0.2.2 + go.sia.tech/coreutils v0.2.4-0.20240809193500-b680c3b225f0 go.sia.tech/jape v0.12.0 go.sia.tech/web/walletd v0.22.3 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index 5f6ec93..102b68e 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,6 @@ go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.sia.tech/core v0.4.2 h1:5VCRuRJAOy0cWwG32IGB0BXQAviXgKRfNXOiU0zSViM= go.sia.tech/core v0.4.2/go.mod h1:cGfGNcyAq1k4oIOsrNpJV/Z/p+20/IMS6vIaofE8nr8= -go.sia.tech/coreutils v0.2.2 h1:WWbuk4lEd5SVB/LoBsPG6+heZN2olZT4yOkRZd3pvpg= -go.sia.tech/coreutils v0.2.2/go.mod h1:0D0NLh0c0pBUNKPoO/rDtyyRapB5j4/gfATNyQO67Rs= go.sia.tech/jape v0.12.0 h1:13fBi7c5X8zxTQ05Cd9ZsIfRJgdvGoZqbEzH861z7BU= go.sia.tech/jape v0.12.0/go.mod h1:wU+h6Wh5olDjkPXjF0tbZ1GDgoZ6VTi4naFw91yyWC4= go.sia.tech/mux v1.2.0 h1:ofa1Us9mdymBbGMY2XH/lSpY8itFsKIo/Aq8zwe+GHU= diff --git a/wallet/events.go b/wallet/events.go deleted file mode 100644 index a42ab7e..0000000 --- a/wallet/events.go +++ /dev/null @@ -1,134 +0,0 @@ -package wallet - -import ( - "encoding/json" - "fmt" - "time" - - "go.sia.tech/core/types" -) - -// event types indicate the source of an event. Events can -// either be created by sending Siacoins between addresses or they can be -// created by consensus (e.g. a miner payout, a siafund claim, or a contract). -const ( - EventTypeMinerPayout = "miner" - EventTypeFoundationSubsidy = "foundation" - - EventTypeV1Transaction = "v1Transaction" - EventTypeV1ContractResolution = "v1ContractResolution" - - EventTypeV2Transaction = "v2Transaction" - EventTypeV2ContractResolution = "v2ContractResolution" - - EventTypeSiafundClaim = "siafundClaim" -) - -type ( - // EventData provides type safety for the Data field of an Event. - EventData interface { - isEvent() bool - } - - // An Event is something interesting that happened on the Sia blockchain. - Event struct { - ID types.Hash256 `json:"id"` - Index types.ChainIndex `json:"index"` - Timestamp time.Time `json:"timestamp"` - MaturityHeight uint64 `json:"maturityHeight"` - Type string `json:"type"` - Data EventData `json:"data"` - Relevant []types.Address `json:"relevant,omitempty"` - } - - // An EventV1Transaction pairs a v1 transaction with its spent siacoin and - // siafund elements. - EventV1Transaction struct { - Transaction types.Transaction `json:"transaction"` - // v1 siacoin inputs do not describe the value of the spent utxo - SpentSiacoinElements []types.SiacoinElement `json:"spentSiacoinElements"` - // v1 siafund inputs do not describe the value of the spent utxo - SpentSiafundElements []types.SiafundElement `json:"spentSiafundElements"` - } - - // An EventV2Transaction is a v2 transaction. - EventV2Transaction types.V2Transaction - - // An EventPayout represents a payout from a siafund claim, a miner, or the - // foundation subsidy. - EventPayout struct { - SiacoinElement types.SiacoinElement `json:"siacoinElement"` - } - - // An EventV1ContractResolution represents a file contract payout from a v1 - // contract. - EventV1ContractResolution struct { - Parent types.FileContractElement `json:"parent"` - SiacoinElement types.SiacoinElement `json:"siacoinElement"` - Missed bool `json:"missed"` - } - - // An EventV2ContractResolution represents a file contract payout from a v2 - // contract. - EventV2ContractResolution struct { - Resolution types.V2FileContractResolution `json:"resolution"` - SiacoinElement types.SiacoinElement `json:"siacoinElement"` - Missed bool `json:"missed"` - } -) - -func (EventPayout) isEvent() bool { return true } -func (EventV1ContractResolution) isEvent() bool { return true } -func (EventV2ContractResolution) isEvent() bool { return true } -func (EventV1Transaction) isEvent() bool { return true } -func (EventV2Transaction) isEvent() bool { return true } - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (e *Event) UnmarshalJSON(b []byte) error { - var je struct { - ID types.Hash256 `json:"id"` - Index types.ChainIndex `json:"index"` - Timestamp time.Time `json:"timestamp"` - MaturityHeight uint64 `json:"maturityHeight"` - Type string `json:"type"` - Data json.RawMessage `json:"data"` - Relevant []types.Address `json:"relevant,omitempty"` - } - if err := json.Unmarshal(b, &je); err != nil { - return err - } - - e.ID = je.ID - e.Index = je.Index - e.Timestamp = je.Timestamp - e.MaturityHeight = je.MaturityHeight - e.Type = je.Type - e.Relevant = je.Relevant - - var err error - switch je.Type { - case EventTypeMinerPayout, EventTypeFoundationSubsidy, EventTypeSiafundClaim: - var data EventPayout - err = json.Unmarshal(je.Data, &data) - e.Data = data - case EventTypeV1ContractResolution: - var data EventV1ContractResolution - err = json.Unmarshal(je.Data, &data) - e.Data = data - case EventTypeV2ContractResolution: - var data EventV2ContractResolution - err = json.Unmarshal(je.Data, &data) - e.Data = data - case EventTypeV1Transaction: - var data EventV1Transaction - err = json.Unmarshal(je.Data, &data) - e.Data = data - case EventTypeV2Transaction: - var data EventV2Transaction - err = json.Unmarshal(je.Data, &data) - e.Data = data - default: - return fmt.Errorf("unknown event type: %v", je.Type) - } - return err -} diff --git a/wallet/wallet.go b/wallet/wallet.go index 4a8678a..95c5631 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -8,6 +8,42 @@ import ( "go.sia.tech/core/consensus" "go.sia.tech/core/types" + "go.sia.tech/coreutils/wallet" +) + +// event types indicate the source of an event. Events can +// either be created by sending Siacoins between addresses or they can be +// created by consensus (e.g. a miner payout, a siafund claim, or a contract). +const ( + EventTypeMinerPayout = wallet.EventTypeMinerPayout + EventTypeFoundationSubsidy = wallet.EventTypeFoundationSubsidy + EventTypeSiafundClaim = wallet.EventTypeSiafundClaim + + EventTypeV1Transaction = wallet.EventTypeV1Transaction + EventTypeV1ContractResolution = wallet.EventTypeV1ContractResolution + + EventTypeV2Transaction = wallet.EventTypeV2Transaction + EventTypeV2ContractResolution = wallet.EventTypeV2ContractResolution +) + +type ( + // An EventPayout represents a miner payout, siafund claim, or foundation + // subsidy. + EventPayout = wallet.EventPayout + // An EventV1Transaction pairs a v1 transaction with its spent siacoin and + // siafund elements. + EventV1Transaction = wallet.EventV1Transaction + // An EventV1ContractResolution represents a file contract payout from a v1 + // contract. + EventV1ContractResolution = wallet.EventV1ContractResolution + // EventV2Transaction is a transaction event that includes the transaction + EventV2Transaction = wallet.EventV2Transaction + // An EventV2ContractResolution represents a file contract payout from a v2 + // contract. + EventV2ContractResolution = wallet.EventV2ContractResolution + + EventData = wallet.EventData + Event = wallet.Event ) type ( @@ -93,7 +129,7 @@ func SignTransaction(cs consensus.State, txn *types.Transaction, sigIndex int, k // AppliedEvents extracts a list of relevant events from a chain update. func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant func(types.Address) bool) (events []Event) { - addEvent := func(id types.Hash256, maturityHeight uint64, eventType string, v EventData, relevant []types.Address) { + addEvent := func(id types.Hash256, maturityHeight uint64, eventType string, v wallet.EventData, relevant []types.Address) { // dedup relevant addresses seen := make(map[types.Address]bool) unique := relevant[:0] @@ -157,7 +193,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f // handle v1 transactions for _, txn := range b.Transactions { addresses := make(map[types.Address]bool) - e := &EventV1Transaction{ + e := &wallet.EventV1Transaction{ Transaction: txn, SpentSiacoinElements: make([]types.SiacoinElement, 0, len(txn.SiacoinInputs)), SpentSiafundElements: make([]types.SiafundElement, 0, len(txn.SiafundInputs)), @@ -193,7 +229,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f sce, ok := sces[sfi.ParentID.ClaimOutputID()] if ok && relevant(sce.SiacoinOutput.Address) { - addEvent(sce.ID, sce.MaturityHeight, EventTypeSiafundClaim, EventPayout{ + addEvent(sce.ID, sce.MaturityHeight, EventTypeSiafundClaim, wallet.EventPayout{ SiacoinElement: sce, }, []types.Address{sfi.ClaimAddress}) } @@ -240,7 +276,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f sce, ok := sces[types.SiafundOutputID(sfi.Parent.ID).V2ClaimOutputID()] if ok && relevant(sfi.ClaimAddress) { - addEvent(sce.ID, sce.MaturityHeight, EventTypeSiafundClaim, EventPayout{ + addEvent(sce.ID, sce.MaturityHeight, EventTypeSiafundClaim, wallet.EventPayout{ SiacoinElement: sce, }, []types.Address{sfi.ClaimAddress}) } @@ -257,7 +293,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f continue } - ev := EventV2Transaction(txn) + ev := wallet.EventV2Transaction(txn) relevant := make([]types.Address, 0, len(addresses)) for addr := range addresses { relevant = append(relevant, addr) @@ -279,7 +315,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f } element := sces[types.FileContractID(fce.ID).ValidOutputID(i)] - addEvent(element.ID, element.MaturityHeight, EventTypeV1ContractResolution, EventV1ContractResolution{ + addEvent(element.ID, element.MaturityHeight, EventTypeV1ContractResolution, wallet.EventV1ContractResolution{ Parent: fce, SiacoinElement: element, Missed: false, @@ -293,7 +329,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f } element := sces[types.FileContractID(fce.ID).MissedOutputID(i)] - addEvent(element.ID, element.MaturityHeight, EventTypeV1ContractResolution, EventV1ContractResolution{ + addEvent(element.ID, element.MaturityHeight, EventTypeV1ContractResolution, wallet.EventV1ContractResolution{ Parent: fce, SiacoinElement: element, Missed: true, @@ -314,7 +350,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f if relevant(fce.V2FileContract.HostOutput.Address) { element := sces[types.FileContractID(fce.ID).V2HostOutputID()] - addEvent(element.ID, element.MaturityHeight, EventTypeV2ContractResolution, EventV2ContractResolution{ + addEvent(element.ID, element.MaturityHeight, EventTypeV2ContractResolution, wallet.EventV2ContractResolution{ Resolution: types.V2FileContractResolution{ Parent: fce, Resolution: res, @@ -326,7 +362,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f if relevant(fce.V2FileContract.RenterOutput.Address) { element := sces[types.FileContractID(fce.ID).V2RenterOutputID()] - addEvent(element.ID, element.MaturityHeight, EventTypeV2ContractResolution, EventV2ContractResolution{ + addEvent(element.ID, element.MaturityHeight, EventTypeV2ContractResolution, wallet.EventV2ContractResolution{ Resolution: types.V2FileContractResolution{ Parent: fce, Resolution: res, @@ -341,7 +377,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f for i := range b.MinerPayouts { if relevant(b.MinerPayouts[i].Address) { element := sces[cs.Index.ID.MinerOutputID(i)] - addEvent(element.ID, element.MaturityHeight, EventTypeMinerPayout, EventPayout{ + addEvent(element.ID, element.MaturityHeight, EventTypeMinerPayout, wallet.EventPayout{ SiacoinElement: element, }, []types.Address{b.MinerPayouts[i].Address}) } @@ -351,7 +387,7 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f if relevant(cs.FoundationPrimaryAddress) { element, ok := sces[cs.Index.ID.FoundationOutputID()] if ok { - addEvent(element.ID, element.MaturityHeight, EventTypeFoundationSubsidy, EventPayout{ + addEvent(element.ID, element.MaturityHeight, EventTypeFoundationSubsidy, wallet.EventPayout{ SiacoinElement: element, }, []types.Address{element.SiacoinOutput.Address}) } diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 09b2f7b..cc5e9cc 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -2980,50 +2980,10 @@ func TestEventTypes(t *testing.T) { t.Fatalf("expected maturity height %v, got %v", maturityHeight, event.MaturityHeight) } - var inflowSum, outflowSum types.Currency - switch ev := event.Data.(type) { - case wallet.EventV1Transaction: - for _, sce := range ev.SpentSiacoinElements { - if sce.SiacoinOutput.Address == addr { - outflowSum = outflowSum.Add(sce.SiacoinOutput.Value) - } - } - for _, sce := range ev.Transaction.SiacoinOutputs { - if sce.Address == addr { - inflowSum = inflowSum.Add(sce.Value) - } - } - case wallet.EventV1ContractResolution: - if ev.SiacoinElement.SiacoinOutput.Address == addr { - inflowSum = ev.SiacoinElement.SiacoinOutput.Value - } - case wallet.EventPayout: - if ev.SiacoinElement.SiacoinOutput.Address == addr { - inflowSum = ev.SiacoinElement.SiacoinOutput.Value - } - case wallet.EventV2ContractResolution: - if ev.SiacoinElement.SiacoinOutput.Address == addr { - inflowSum = ev.SiacoinElement.SiacoinOutput.Value - } - case wallet.EventV2Transaction: - for _, sce := range ev.SiacoinInputs { - if sce.Parent.SiacoinOutput.Address == addr { - outflowSum = outflowSum.Add(sce.Parent.SiacoinOutput.Value) - } - } - for _, sce := range ev.SiacoinOutputs { - if sce.Address == addr { - inflowSum = inflowSum.Add(sce.Value) - } - } - default: - t.Fatalf("unexpected event type %T", ev) - } - - if !inflowSum.Equals(expectedInflow) { - t.Fatalf("expected inflow %v, got %v", expectedInflow, inflowSum) - } else if !outflowSum.Equals(expectedOutflow) { - t.Fatalf("expected outflow %v, got %v", expectedOutflow, outflowSum) + if !event.SiacoinInflow().Equals(expectedInflow) { + t.Fatalf("expected inflow %v, got %v", expectedInflow, event.SiacoinInflow()) + } else if !event.SiacoinOutflow().Equals(expectedOutflow) { + t.Fatalf("expected outflow %v, got %v", expectedOutflow, event.SiacoinOutflow()) } return } From b4935767c2b256ea47bb806fa6cdd03c7c84e9ce Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Fri, 9 Aug 2024 12:56:03 -0700 Subject: [PATCH 2/5] wallet: fix lint --- wallet/wallet.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wallet/wallet.go b/wallet/wallet.go index 95c5631..709b1c3 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -42,8 +42,10 @@ type ( // contract. EventV2ContractResolution = wallet.EventV2ContractResolution + // EventData is the data associated with an event. EventData = wallet.EventData - Event = wallet.Event + // An Event is a record of a consensus event that affects the wallet. + Event = wallet.Event ) type ( From d48924947f51612a0488b4b51c1aca9e312ca5b7 Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Fri, 9 Aug 2024 13:01:41 -0700 Subject: [PATCH 3/5] deps: update coreutils --- go.mod | 4 +--- go.sum | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8ce388c..341bd7d 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,10 @@ go 1.21.8 toolchain go1.22.3 -replace go.sia.tech/coreutils => ../coreutils - require ( github.com/mattn/go-sqlite3 v1.14.22 go.sia.tech/core v0.4.2 - go.sia.tech/coreutils v0.2.4-0.20240809193500-b680c3b225f0 + go.sia.tech/coreutils v0.2.4 go.sia.tech/jape v0.12.0 go.sia.tech/web/walletd v0.22.3 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index 102b68e..ceec7a3 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.sia.tech/core v0.4.2 h1:5VCRuRJAOy0cWwG32IGB0BXQAviXgKRfNXOiU0zSViM= go.sia.tech/core v0.4.2/go.mod h1:cGfGNcyAq1k4oIOsrNpJV/Z/p+20/IMS6vIaofE8nr8= +go.sia.tech/coreutils v0.2.4 h1:jEojRSz+O7Rap1zACUbAS+Hzvcdw2+0jx94iBD27eOo= +go.sia.tech/coreutils v0.2.4/go.mod h1:0D0NLh0c0pBUNKPoO/rDtyyRapB5j4/gfATNyQO67Rs= go.sia.tech/jape v0.12.0 h1:13fBi7c5X8zxTQ05Cd9ZsIfRJgdvGoZqbEzH861z7BU= go.sia.tech/jape v0.12.0/go.mod h1:wU+h6Wh5olDjkPXjF0tbZ1GDgoZ6VTi4naFw91yyWC4= go.sia.tech/mux v1.2.0 h1:ofa1Us9mdymBbGMY2XH/lSpY8itFsKIo/Aq8zwe+GHU= From 1114e5bd3066862c21c07f5869de4f03aba5a90a Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Fri, 9 Aug 2024 13:31:59 -0700 Subject: [PATCH 4/5] sqlite: fix missing relevant address --- persist/sqlite/addresses.go | 2 +- wallet/wallet_test.go | 87 ++++++++++++++++++++++++------------- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/persist/sqlite/addresses.go b/persist/sqlite/addresses.go index 497742f..52f4ec4 100644 --- a/persist/sqlite/addresses.go +++ b/persist/sqlite/addresses.go @@ -47,7 +47,7 @@ func (s *Store) AddressEvents(address types.Address, offset, limit int) (events if err != nil { return fmt.Errorf("failed to scan event: %w", err) } - + event.Relevant = []types.Address{address} events = append(events, event) } return rows.Err() diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index cc5e9cc..13cd74f 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -1459,16 +1459,22 @@ func TestEvents(t *testing.T) { waitForBlock(t, cm, db) // check the payout was received - if events, err := wm.AddressEvents(addr, 0, 100); err != nil { + events, err := wm.AddressEvents(addr, 0, 100) + if err != nil { t.Fatal(err) } else if len(events) != 1 { t.Fatalf("expected 1 events, got %v", len(events)) } else if events[0].Type != wallet.EventTypeMinerPayout { t.Fatalf("expected miner payout event, got %v", events[0].Type) - } else if events2, err := wm.Events([]types.Hash256{events[0].ID}); err != nil { + } + + expected := events[0] + expected.Relevant = nil // clear the relevant field for deep equal + events2, err := wm.Events([]types.Hash256{events[0].ID}) + if err != nil { t.Fatalf("expected to get event: %v", err) - } else if !reflect.DeepEqual(events2[0], events[0]) { - t.Fatalf("expected event %v to match %v", events[0], events2) + } else if !reflect.DeepEqual(events2[0], expected) { + t.Fatalf("expected event %v to match %v", expected, events2[0]) } assertBalance(t, addr, types.ZeroCurrency, expectedBalance1, 0) @@ -1527,29 +1533,40 @@ func TestEvents(t *testing.T) { assertBalance(t, addr2, expectedBalance1.Div64(2), types.ZeroCurrency, cm.TipState().SiafundCount()) // check the events for the transaction - if events, err := wm.AddressEvents(addr, 0, 100); err != nil { + events, err = wm.AddressEvents(addr, 0, 100) + if err != nil { t.Fatal(err) } else if len(events) != 2 { t.Fatalf("expected 2 events, got %v", len(events)) } else if events[0].Type != wallet.EventTypeV2Transaction { t.Fatalf("expected transaction event, got %v", events[0].Type) - } else if events2, err := wm.Events([]types.Hash256{events[0].ID}); err != nil { + } + + expected = events[0] + expected.Relevant = nil // clear the relevant field for deep equal + if events2, err := wm.Events([]types.Hash256{expected.ID}); err != nil { t.Fatalf("expected to get event: %v", err) - } else if !reflect.DeepEqual(events2[0], events[0]) { - t.Fatalf("expected event %v to match %v", events[0], events2) + } else if !reflect.DeepEqual(events2[0], expected) { + t.Fatalf("expected event %v to match %v", expected, events2) } // check the events for the second address - if events, err := wm.AddressEvents(addr2, 0, 100); err != nil { + events, err = wm.AddressEvents(addr2, 0, 100) + if err != nil { t.Fatal(err) } else if len(events) != 2 { t.Fatalf("expected 2 event, got %v", len(events)) } else if events[0].Type != wallet.EventTypeV2Transaction { t.Fatalf("expected transaction event, got %v", events[0].Type) - } else if events2, err := wm.Events([]types.Hash256{events[0].ID}); err != nil { + } + + expected = events[0] + expected.Relevant = nil // clear the relevant field for deep equal + events2, err = wm.Events([]types.Hash256{events[0].ID}) + if err != nil { t.Fatalf("expected to get event: %v", err) - } else if !reflect.DeepEqual(events2[0], events[0]) { - t.Fatalf("expected event %v to match %v", events[0], events2) + } else if !reflect.DeepEqual(events2[0], expected) { + t.Fatalf("expected event %v to match %v", expected, events2[0]) } sf, err := wm.AddressSiafundOutputs(addr2, 0, 100) @@ -1586,29 +1603,39 @@ func TestEvents(t *testing.T) { assertBalance(t, addr2, expectedBalance1.Div64(2), types.ZeroCurrency, 0) // check the events for the transaction - if events, err := wm.AddressEvents(addr2, 0, 100); err != nil { + events, err = wm.AddressEvents(addr2, 0, 100) + if err != nil { t.Fatal(err) } else if len(events) != 4 { t.Fatalf("expected 4 events, got %v", len(events)) } else if events[0].Type != wallet.EventTypeSiafundClaim { t.Fatalf("expected transaction event, got %v", events[0].Type) - } else if events2, err := wm.Events([]types.Hash256{events[0].ID}); err != nil { + } + + expected = events[0] + expected.Relevant = nil // clear the relevant field for deep equal + if events2, err := wm.Events([]types.Hash256{expected.ID}); err != nil { t.Fatalf("expected to get event: %v", err) - } else if !reflect.DeepEqual(events2[0], events[0]) { - t.Fatalf("expected event %v to match %v", events[0], events2) + } else if !reflect.DeepEqual(events2[0], expected) { + t.Fatalf("expected event %v to match %v", expected, events2) } // check the events for the first address - if events, err := wm.AddressEvents(addr, 0, 100); err != nil { + events, err = wm.AddressEvents(addr, 0, 100) + if err != nil { t.Fatal(err) } else if len(events) != 3 { t.Fatalf("expected 3 events, got %v", len(events)) } else if events[0].Type != wallet.EventTypeV2Transaction { t.Fatalf("expected transaction event, got %v", events[0].Type) - } else if events2, err := wm.Events([]types.Hash256{events[0].ID}); err != nil { + } + + expected = events[0] + expected.Relevant = nil // clear the relevant field for deep equal + if events2, err := wm.Events([]types.Hash256{expected.ID}); err != nil { t.Fatalf("expected to get event: %v", err) - } else if !reflect.DeepEqual(events2[0], events[0]) { - t.Fatalf("expected event %v to match %v", events[0], events2) + } else if !reflect.DeepEqual(events2[0], expected) { + t.Fatalf("expected event %v to match %v", expected, events2) } } @@ -2964,7 +2991,7 @@ func TestEventTypes(t *testing.T) { return filtered } - assertEvent := func(id types.Hash256, eventType string, expectedInflow, expectedOutflow types.Currency, maturityHeight uint64) { + assertEvent := func(t *testing.T, id types.Hash256, eventType string, expectedInflow, expectedOutflow types.Currency, maturityHeight uint64) { t.Helper() events, err := wm.AddressEvents(addr, 0, 100) @@ -2993,7 +3020,7 @@ func TestEventTypes(t *testing.T) { // miner payout event mineBlock(1, addr) - assertEvent(types.Hash256(cm.Tip().ID.MinerOutputID(0)), wallet.EventTypeMinerPayout, genesisState.BlockReward(), types.ZeroCurrency, genesisState.MaturityHeight()) + assertEvent(t, types.Hash256(cm.Tip().ID.MinerOutputID(0)), wallet.EventTypeMinerPayout, genesisState.BlockReward(), types.ZeroCurrency, genesisState.MaturityHeight()) // mine until the payout matures mineBlock(int(cm.TipState().MaturityHeight()), types.VoidAddress) @@ -3035,7 +3062,7 @@ func TestEventTypes(t *testing.T) { } // mine a block to confirm the transaction mineBlock(1, types.VoidAddress) - assertEvent(types.Hash256(txn.ID()), wallet.EventTypeV1Transaction, sce[0].SiacoinOutput.Value.Sub(types.Siacoins(1000)), sce[0].SiacoinOutput.Value, cm.Tip().Height) + assertEvent(t, types.Hash256(txn.ID()), wallet.EventTypeV1Transaction, sce[0].SiacoinOutput.Value.Sub(types.Siacoins(1000)), sce[0].SiacoinOutput.Value, cm.Tip().Height) }) t.Run("v1 contract resolution - missed", func(t *testing.T) { @@ -3093,7 +3120,7 @@ func TestEventTypes(t *testing.T) { // mine until the contract expires to trigger the resolution event blocksRemaining := int(fc.WindowEnd - cm.Tip().Height) mineBlock(blocksRemaining, types.VoidAddress) - assertEvent(types.Hash256(txn.FileContractID(0).MissedOutputID(0)), wallet.EventTypeV1ContractResolution, contractPayout, types.ZeroCurrency, fc.WindowEnd+144) + assertEvent(t, types.Hash256(txn.FileContractID(0).MissedOutputID(0)), wallet.EventTypeV1ContractResolution, contractPayout, types.ZeroCurrency, fc.WindowEnd+144) }) t.Run("v2 transaction", func(t *testing.T) { @@ -3127,7 +3154,7 @@ func TestEventTypes(t *testing.T) { } // mine a block to confirm the transaction mineBlock(1, types.VoidAddress) - assertEvent(types.Hash256(txn.ID()), wallet.EventTypeV2Transaction, sce[0].SiacoinOutput.Value.Sub(types.Siacoins(1000)), sce[0].SiacoinOutput.Value, cm.Tip().Height) + assertEvent(t, types.Hash256(txn.ID()), wallet.EventTypeV2Transaction, sce[0].SiacoinOutput.Value.Sub(types.Siacoins(1000)), sce[0].SiacoinOutput.Value, cm.Tip().Height) }) t.Run("v2 contract resolution - expired", func(t *testing.T) { @@ -3218,7 +3245,7 @@ func TestEventTypes(t *testing.T) { } // mine a block to confirm the resolution mineBlock(1, types.VoidAddress) - assertEvent(types.Hash256(types.FileContractID(fce.ID).V2RenterOutputID()), wallet.EventTypeV2ContractResolution, renterPayout, types.ZeroCurrency, cm.Tip().Height+144) + assertEvent(t, types.Hash256(types.FileContractID(fce.ID).V2RenterOutputID()), wallet.EventTypeV2ContractResolution, renterPayout, types.ZeroCurrency, cm.Tip().Height+144) }) t.Run("v2 contract resolution - storage proof", func(t *testing.T) { @@ -3315,7 +3342,7 @@ func TestEventTypes(t *testing.T) { t.Fatal(err) } mineBlock(1, types.VoidAddress) - assertEvent(types.Hash256(types.FileContractID(fce.ID).V2HostOutputID()), wallet.EventTypeV2ContractResolution, renterPayout, types.ZeroCurrency, cm.Tip().Height+144) + assertEvent(t, types.Hash256(types.FileContractID(fce.ID).V2HostOutputID()), wallet.EventTypeV2ContractResolution, renterPayout, types.ZeroCurrency, cm.Tip().Height+144) }) t.Run("v2 contract resolution - renewal", func(t *testing.T) { @@ -3461,7 +3488,7 @@ func TestEventTypes(t *testing.T) { t.Fatal(err) } mineBlock(1, types.VoidAddress) - assertEvent(types.Hash256(types.FileContractID(fce.ID).V2RenterOutputID()), wallet.EventTypeV2ContractResolution, renterPayout, types.ZeroCurrency, cm.Tip().Height+144) + assertEvent(t, types.Hash256(types.FileContractID(fce.ID).V2RenterOutputID()), wallet.EventTypeV2ContractResolution, renterPayout, types.ZeroCurrency, cm.Tip().Height+144) }) t.Run("v2 contract resolution - finalization", func(t *testing.T) { @@ -3561,7 +3588,7 @@ func TestEventTypes(t *testing.T) { t.Fatal(err) } mineBlock(1, types.VoidAddress) - assertEvent(types.Hash256(types.FileContractID(fce.ID).V2RenterOutputID()), wallet.EventTypeV2ContractResolution, renterPayout, types.ZeroCurrency, cm.Tip().Height+144) + assertEvent(t, types.Hash256(types.FileContractID(fce.ID).V2RenterOutputID()), wallet.EventTypeV2ContractResolution, renterPayout, types.ZeroCurrency, cm.Tip().Height+144) }) t.Run("siafund claim", func(t *testing.T) { @@ -3599,6 +3626,6 @@ func TestEventTypes(t *testing.T) { } // mine a block to confirm the transaction mineBlock(1, types.VoidAddress) - assertEvent(types.Hash256(types.SiafundOutputID(sfe[0].ID).V2ClaimOutputID()), wallet.EventTypeSiafundClaim, claimValue, types.ZeroCurrency, cm.Tip().Height+144) + assertEvent(t, types.Hash256(types.SiafundOutputID(sfe[0].ID).V2ClaimOutputID()), wallet.EventTypeSiafundClaim, claimValue, types.ZeroCurrency, cm.Tip().Height+144) }) } From ff6bc3717192b543c4b391cf779d435e333733bb Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Fri, 9 Aug 2024 13:45:51 -0700 Subject: [PATCH 5/5] wallet: clear file contract element proofs --- go.mod | 4 ++-- go.sum | 8 ++++---- wallet/wallet.go | 14 ++++---------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 341bd7d..943cdfc 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,8 @@ toolchain go1.22.3 require ( github.com/mattn/go-sqlite3 v1.14.22 - go.sia.tech/core v0.4.2 - go.sia.tech/coreutils v0.2.4 + go.sia.tech/core v0.4.3 + go.sia.tech/coreutils v0.2.5 go.sia.tech/jape v0.12.0 go.sia.tech/web/walletd v0.22.3 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index ceec7a3..18b37fc 100644 --- a/go.sum +++ b/go.sum @@ -12,10 +12,10 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= -go.sia.tech/core v0.4.2 h1:5VCRuRJAOy0cWwG32IGB0BXQAviXgKRfNXOiU0zSViM= -go.sia.tech/core v0.4.2/go.mod h1:cGfGNcyAq1k4oIOsrNpJV/Z/p+20/IMS6vIaofE8nr8= -go.sia.tech/coreutils v0.2.4 h1:jEojRSz+O7Rap1zACUbAS+Hzvcdw2+0jx94iBD27eOo= -go.sia.tech/coreutils v0.2.4/go.mod h1:0D0NLh0c0pBUNKPoO/rDtyyRapB5j4/gfATNyQO67Rs= +go.sia.tech/core v0.4.3 h1:XEX7v6X8eJh4zyOkSHYi6FsyD+N/OEKw/NIigaaWPAU= +go.sia.tech/core v0.4.3/go.mod h1:cGfGNcyAq1k4oIOsrNpJV/Z/p+20/IMS6vIaofE8nr8= +go.sia.tech/coreutils v0.2.5 h1:oMnBGMBRfxhLzTH1ZDBg0Ep0QLE2GE1lND9yfzOzenA= +go.sia.tech/coreutils v0.2.5/go.mod h1:Pg9eE3xL25couNL/vYrtCWP5uXkVvC+SUcMVh1/E7+I= go.sia.tech/jape v0.12.0 h1:13fBi7c5X8zxTQ05Cd9ZsIfRJgdvGoZqbEzH861z7BU= go.sia.tech/jape v0.12.0/go.mod h1:wU+h6Wh5olDjkPXjF0tbZ1GDgoZ6VTi4naFw91yyWC4= go.sia.tech/mux v1.2.0 h1:ofa1Us9mdymBbGMY2XH/lSpY8itFsKIo/Aq8zwe+GHU= diff --git a/wallet/wallet.go b/wallet/wallet.go index 709b1c3..c968e56 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -173,8 +173,6 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f // collect all elements sces := make(map[types.SiacoinOutputID]types.SiacoinElement) sfes := make(map[types.SiafundOutputID]types.SiafundElement) - fces := make(map[types.FileContractID]types.FileContractElement) - v2fces := make(map[types.FileContractID]types.V2FileContractElement) cu.ForEachSiacoinElement(func(sce types.SiacoinElement, _, _ bool) { sce.MerkleProof = nil sces[types.SiacoinOutputID(sce.ID)] = sce @@ -183,14 +181,6 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f sfe.MerkleProof = nil sfes[types.SiafundOutputID(sfe.ID)] = sfe }) - cu.ForEachFileContractElement(func(fce types.FileContractElement, _ bool, rev *types.FileContractElement, resolved, valid bool) { - fce.MerkleProof = nil - fces[types.FileContractID(fce.ID)] = fce - }) - cu.ForEachV2FileContractElement(func(fce types.V2FileContractElement, _ bool, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) { - fce.MerkleProof = nil - v2fces[types.FileContractID(fce.ID)] = fce - }) // handle v1 transactions for _, txn := range b.Transactions { @@ -309,6 +299,8 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f return } + fce.MerkleProof = nil + if valid { for i := range fce.FileContract.ValidProofOutputs { address := fce.FileContract.ValidProofOutputs[i].Address @@ -345,6 +337,8 @@ func AppliedEvents(cs consensus.State, b types.Block, cu ChainUpdate, relevant f return } + fce.MerkleProof = nil + var missed bool if _, ok := res.(*types.V2FileContractExpiration); ok { missed = true