From a3687a969fee20319e3e608025c09b4b2ca11090 Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Tue, 28 May 2024 09:21:18 -0700 Subject: [PATCH] wallet: address comments --- testutil/wallet.go | 8 -------- wallet/events.go | 20 +++++++++++++++++++- wallet/update.go | 15 ++++++++------- wallet/wallet.go | 14 +++++++++++--- wallet/wallet_test.go | 8 ++++---- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/testutil/wallet.go b/testutil/wallet.go index 229005a..e1fc4a3 100644 --- a/testutil/wallet.go +++ b/testutil/wallet.go @@ -44,14 +44,6 @@ func (et *ephemeralWalletUpdateTxn) UpdateStateElements(elements []types.StateEl return nil } -func (et *ephemeralWalletUpdateTxn) AddEvents(events []wallet.Event) error { - et.store.events = append(events, et.store.events...) - sort.Slice(et.store.events, func(i, j int) bool { - return et.store.events[i].MaturityHeight < et.store.events[j].MaturityHeight - }) - return nil -} - func (et *ephemeralWalletUpdateTxn) ApplyIndex(index types.ChainIndex, created, spent []types.SiacoinElement, events []wallet.Event) error { for _, se := range spent { if _, ok := et.store.utxos[types.SiacoinOutputID(se.ID)]; !ok { diff --git a/wallet/events.go b/wallet/events.go index 6753df8..662b789 100644 --- a/wallet/events.go +++ b/wallet/events.go @@ -48,6 +48,17 @@ type ( Missed bool `json:"missed"` } + // EventV1Transaction is a transaction event that includes the transaction + EventV1Transaction types.Transaction + + // EventV2Transaction is a transaction event that includes the transaction + EventV2Transaction types.V2Transaction + + // EventData contains the data associated with an event. + EventData interface { + isEvent() bool + } + // An Event is a transaction or other event that affects the wallet including // miner payouts, siafund claims, and file contract payouts. Event struct { @@ -56,8 +67,15 @@ type ( Inflow types.Currency `json:"inflow"` Outflow types.Currency `json:"outflow"` Type string `json:"type"` - Data any `json:"data"` + Data EventData `json:"data"` MaturityHeight uint64 `json:"maturityHeight"` Timestamp time.Time `json:"timestamp"` } ) + +func (EventMinerPayout) isEvent() bool { return true } +func (EventFoundationSubsidy) isEvent() bool { return true } +func (EventV1ContractPayout) isEvent() bool { return true } +func (EventV2ContractPayout) isEvent() bool { return true } +func (EventV1Transaction) isEvent() bool { return true } +func (EventV2Transaction) isEvent() bool { return true } diff --git a/wallet/update.go b/wallet/update.go index 7b6fa67..cd4ed54 100644 --- a/wallet/update.go +++ b/wallet/update.go @@ -51,6 +51,7 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [ cs := cau.State block := cau.Block index := cs.Index + maturityHeight := cs.MaturityHeight() siacoinElements := make(map[types.SiacoinOutputID]types.SiacoinElement) // cache the value of spent siacoin elements to use when calculating outflow @@ -60,7 +61,7 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [ } }) - addEvent := func(id types.Hash256, data any) { + addEvent := func(id types.Hash256, data EventData) { ev := Event{ ID: id, Index: index, @@ -72,12 +73,12 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [ case EventMinerPayout: ev.Inflow = data.SiacoinElement.SiacoinOutput.Value ev.Type = EventTypeMinerPayout - ev.MaturityHeight = cs.MaturityHeight() + ev.MaturityHeight = maturityHeight case EventFoundationSubsidy: ev.Inflow = data.SiacoinElement.SiacoinOutput.Value ev.Type = EventTypeFoundationSubsidy - ev.MaturityHeight = cs.MaturityHeight() - case types.Transaction: + ev.MaturityHeight = maturityHeight + case EventV1Transaction: for _, si := range data.SiacoinInputs { if si.UnlockConditions.UnlockHash() == walletAddress { ev.Outflow = ev.Outflow.Add(siacoinElements[si.ParentID].SiacoinOutput.Value) @@ -95,7 +96,7 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [ ev.Inflow = data.SiacoinElement.SiacoinOutput.Value ev.Type = EventTypeV1Contract ev.MaturityHeight = cs.MaturityHeight() - case types.V2Transaction: + case EventV2Transaction: for _, si := range data.SiacoinInputs { if si.SatisfiedPolicy.Policy.Address() == walletAddress { ev.Outflow = ev.Outflow.Add(siacoinElements[types.SiacoinOutputID(si.Parent.ID)].SiacoinOutput.Value) @@ -136,7 +137,7 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [ if !relevantV1Txn(txn) { continue } - addEvent(types.Hash256(txn.ID()), txn) + addEvent(types.Hash256(txn.ID()), EventV1Transaction(txn)) } relevantV2Txn := func(txn types.V2Transaction) bool { @@ -157,7 +158,7 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [ if !relevantV2Txn(txn) { continue } - addEvent(types.Hash256(txn.ID()), txn) + addEvent(types.Hash256(txn.ID()), EventV2Transaction(txn)) } cau.ForEachFileContractElement(func(fce types.FileContractElement, rev *types.FileContractElement, resolved bool, valid bool) { diff --git a/wallet/wallet.go b/wallet/wallet.go index 8a39f48..d016ae1 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -347,6 +347,10 @@ func (sw *SingleAddressWallet) selectUTXOs(amount types.Currency, inputs int, us // will not be available to future calls to FundTransaction unless ReleaseInputs // is called. func (sw *SingleAddressWallet) FundTransaction(txn *types.Transaction, amount types.Currency, useUnconfirmed bool) ([]types.Hash256, error) { + if amount.IsZero() { + return nil, nil + } + sw.mu.Lock() defer sw.mu.Unlock() @@ -408,6 +412,10 @@ func (sw *SingleAddressWallet) SignTransaction(txn *types.Transaction, toSign [] // The returned consensus state should be used to calculate the input signature // hash and as the basis for AddV2PoolTransactions. func (sw *SingleAddressWallet) FundV2Transaction(txn *types.V2Transaction, amount types.Currency, useUnconfirmed bool) (consensus.State, []int, error) { + if amount.IsZero() { + return sw.cm.TipState(), nil, nil + } + sw.mu.Lock() defer sw.mu.Unlock() @@ -488,7 +496,7 @@ func (sw *SingleAddressWallet) UnconfirmedTransactions() (annotated []Event, err } timestamp := time.Now().Truncate(time.Second) - addEvent := func(id types.Hash256, eventType string, data any, inflow, outflow types.Currency) { + addEvent := func(id types.Hash256, eventType string, data EventData, inflow, outflow types.Currency) { ev := Event{ ID: id, Index: index, @@ -522,7 +530,7 @@ func (sw *SingleAddressWallet) UnconfirmedTransactions() (annotated []Event, err continue } - addEvent(types.Hash256(txn.ID()), EventTypeV1Transaction, txn, inflow, outflow) + addEvent(types.Hash256(txn.ID()), EventTypeV1Transaction, EventV1Transaction(txn), inflow, outflow) } for _, txn := range sw.cm.V2PoolTransactions() { @@ -546,7 +554,7 @@ func (sw *SingleAddressWallet) UnconfirmedTransactions() (annotated []Event, err continue } - addEvent(types.Hash256(txn.ID()), EventTypeV2Transaction, txn, inflow, outflow) + addEvent(types.Hash256(txn.ID()), EventTypeV2Transaction, EventV2Transaction(txn), inflow, outflow) } return annotated, nil } diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 6f15d00..d285afa 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -222,7 +222,7 @@ func TestWallet(t *testing.T) { t.Fatalf("expected 2 transactions, got %v", len(events)) } else if events[0].ID != types.Hash256(txn.ID()) { t.Fatalf("expected transaction %v, got %v", txn.ID(), events[1].ID) - } else if n := len((events[0].Data.(types.Transaction)).SiacoinOutputs); n != 20 { + } else if n := len((events[0].Data.(wallet.EventV1Transaction)).SiacoinOutputs); n != 20 { t.Fatalf("expected 20 outputs, got %v", n) } @@ -606,7 +606,7 @@ func TestReorg(t *testing.T) { t.Fatalf("expected 2 transactions, got %v", len(events)) } else if events[0].ID != types.Hash256(txn.ID()) { t.Fatalf("expected transaction %v, got %v", txn.ID(), events[1].ID) - } else if n := len((events[0].Data.(types.Transaction)).SiacoinOutputs); n != 20 { + } else if n := len((events[0].Data.(wallet.EventV1Transaction)).SiacoinOutputs); n != 20 { t.Fatalf("expected 20 outputs, got %v", n) } @@ -870,7 +870,7 @@ func TestWalletV2(t *testing.T) { t.Fatalf("expected 2 transactions, got %v", len(events)) } else if events[0].ID != types.Hash256(txn.ID()) { t.Fatalf("expected transaction %v, got %v", txn.ID(), events[1].ID) - } else if n := len((events[0].Data.(types.Transaction)).SiacoinOutputs); n != 20 { + } else if n := len((events[0].Data.(wallet.EventV1Transaction)).SiacoinOutputs); n != 20 { t.Fatalf("expected 20 outputs, got %v", n) } @@ -1091,7 +1091,7 @@ func TestReorgV2(t *testing.T) { t.Fatalf("expected 2 transactions, got %v", len(events)) } else if events[0].ID != types.Hash256(txn.ID()) { t.Fatalf("expected transaction %v, got %v", txn.ID(), events[1].ID) - } else if n := len((events[0].Data.(types.V2Transaction)).SiacoinOutputs); n != 20 { + } else if n := len((events[0].Data.(wallet.EventV2Transaction)).SiacoinOutputs); n != 20 { t.Fatalf("expected 20 outputs, got %v", n) }