@@ -152,83 +152,88 @@ func annotateLocalScriptKeys(ctx context.Context, vPkt *tappsbt.VPacket,
152
152
func createChangeOutput (ctx context.Context , vPkt * tappsbt.VPacket ,
153
153
keyRing KeyRing , fullValue bool , changeAmount uint64 ) error {
154
154
155
+ // If we're spending the full value, we don't need a change output. We
156
+ // currently assume that if it's a full-value non-interactive spend that
157
+ // the packet was created with the correct function in the tappsbt
158
+ // packet that adds the NUMS script key output for the tombstone. If
159
+ // the user doesn't set that, then an error will be returned from the
160
+ // tapsend.PrepareOutputAssets function. But we should probably change
161
+ // that and allow the user to specify a minimum packet template and add
162
+ // whatever else is needed to it automatically.
163
+ if fullValue {
164
+ return nil
165
+ }
166
+
155
167
// We expect some change back, or have passive assets to commit to, so
156
168
// let's make sure we create a transfer output.
157
- var (
158
- changeOut * tappsbt.VOutput
159
- err error
160
- )
161
- if ! fullValue {
162
- // Do we need to add a change output?
163
- changeOut , err = vPkt .SplitRootOutput ()
164
- if err != nil {
165
- lastOut := vPkt .Outputs [len (vPkt .Outputs )- 1 ]
166
- splitOutIndex := lastOut .AnchorOutputIndex + 1
167
- changeOut = & tappsbt.VOutput {
168
- Type : tappsbt .TypeSplitRoot ,
169
- Interactive : lastOut .Interactive ,
170
- AnchorOutputIndex : splitOutIndex ,
171
-
172
- // We want to handle deriving a real key in a
173
- // generic manner, so we'll do that just below.
174
- ScriptKey : asset .NUMSScriptKey ,
175
- }
176
-
177
- vPkt .Outputs = append (vPkt .Outputs , changeOut )
169
+ changeOut , err := vPkt .SplitRootOutput ()
170
+ if err != nil {
171
+ lastOut := vPkt .Outputs [len (vPkt .Outputs )- 1 ]
172
+ splitOutIndex := lastOut .AnchorOutputIndex + 1
173
+ changeOut = & tappsbt.VOutput {
174
+ Type : tappsbt .TypeSplitRoot ,
175
+ Interactive : lastOut .Interactive ,
176
+ AnchorOutputIndex : splitOutIndex ,
177
+
178
+ // We want to handle deriving a real key in a
179
+ // generic manner, so we'll do that just below.
180
+ ScriptKey : asset .NUMSScriptKey ,
178
181
}
179
182
180
- // Since we know we're going to receive some change back, we
181
- // need to make sure it is going to an address that we control.
182
- // This should only be the case where we create the default
183
- // change output with the NUMS key to avoid deriving too many
184
- // keys prematurely. We don't need to derive a new key if we
185
- // only have passive assets to commit to, since they all have
186
- // their own script key and the output is more of a placeholder
187
- // to attach the passive assets to.
188
- unSpendable , err := changeOut .ScriptKey .IsUnSpendable ()
183
+ vPkt .Outputs = append (vPkt .Outputs , changeOut )
184
+ }
185
+
186
+ // Since we know we're going to receive some change back, we
187
+ // need to make sure it is going to an address that we control.
188
+ // This should only be the case where we create the default
189
+ // change output with the NUMS key to avoid deriving too many
190
+ // keys prematurely. We don't need to derive a new key if we
191
+ // only have passive assets to commit to, since they all have
192
+ // their own script key and the output is more of a placeholder
193
+ // to attach the passive assets to.
194
+ unSpendable , err := changeOut .ScriptKey .IsUnSpendable ()
195
+ if err != nil {
196
+ return fmt .Errorf ("cannot determine if script key is " +
197
+ "spendable: %w" , err )
198
+ }
199
+ if unSpendable {
200
+ changeScriptKey , err := keyRing .DeriveNextKey (
201
+ ctx , asset .TaprootAssetsKeyFamily ,
202
+ )
189
203
if err != nil {
190
- return fmt .Errorf ("cannot determine if script key is " +
191
- "spendable: %w" , err )
192
- }
193
- if unSpendable {
194
- changeScriptKey , err := keyRing .DeriveNextKey (
195
- ctx , asset .TaprootAssetsKeyFamily ,
196
- )
197
- if err != nil {
198
- return err
199
- }
200
-
201
- // We'll assume BIP-0086 everywhere, and use the tweaked
202
- // key from here on out.
203
- changeOut .ScriptKey = asset .NewScriptKeyBip86 (
204
- changeScriptKey ,
205
- )
204
+ return err
206
205
}
207
206
208
- // For existing change outputs, we'll just update the amount
209
- // since we might not have known what coin would've been
210
- // selected and how large the change would turn out to be.
211
- changeOut .Amount = changeAmount
212
-
213
- // The asset version of the output should be the max of the set
214
- // of input versions. We need to set this now as in
215
- // PrepareOutputAssets locators are created which includes the
216
- // version from the vOut. If we don't set it here, a v1 asset
217
- // spent that becomes change will be a v0 if combined with such
218
- // inputs.
219
- //
220
- // TODO(roasbeef): remove as not needed?
221
- maxVersion := func (maxVersion asset.Version ,
222
- vInput * tappsbt.VInput ) asset.Version {
223
-
224
- if vInput .Asset ().Version > maxVersion {
225
- return vInput .Asset ().Version
226
- }
227
-
228
- return maxVersion
207
+ // We'll assume BIP-0086 everywhere, and use the tweaked
208
+ // key from here on out.
209
+ changeOut .ScriptKey = asset .NewScriptKeyBip86 (
210
+ changeScriptKey ,
211
+ )
212
+ }
213
+
214
+ // For existing change outputs, we'll just update the amount
215
+ // since we might not have known what coin would've been
216
+ // selected and how large the change would turn out to be.
217
+ changeOut .Amount = changeAmount
218
+
219
+ // The asset version of the output should be the max of the set
220
+ // of input versions. We need to set this now as in
221
+ // PrepareOutputAssets locators are created which includes the
222
+ // version from the vOut. If we don't set it here, a v1 asset
223
+ // spent that becomes change will be a v0 if combined with such
224
+ // inputs.
225
+ //
226
+ // TODO(roasbeef): remove as not needed?
227
+ maxVersion := func (maxVersion asset.Version ,
228
+ vInput * tappsbt.VInput ) asset.Version {
229
+
230
+ if vInput .Asset ().Version > maxVersion {
231
+ return vInput .Asset ().Version
229
232
}
230
- changeOut .AssetVersion = fn .Reduce (vPkt .Inputs , maxVersion )
233
+
234
+ return maxVersion
231
235
}
236
+ changeOut .AssetVersion = fn .Reduce (vPkt .Inputs , maxVersion )
232
237
233
238
return nil
234
239
}
0 commit comments