| 252 | } |
| 253 | |
| 254 | func (a *API) waitForTxInBlock(ctx context.Context, tx *legacy.Tx, height uint64) (uint64, error) { |
| 255 | for { |
| 256 | height++ |
| 257 | select { |
| 258 | case <-ctx.Done(): |
| 259 | return 0, ctx.Err() |
| 260 | |
| 261 | case <-a.chain.BlockWaiter(height): |
| 262 | b, err := a.chain.GetBlock(ctx, height) |
| 263 | if err != nil { |
| 264 | return 0, errors.Wrap(err, "getting block that just landed") |
| 265 | } |
| 266 | for _, confirmed := range b.Transactions { |
| 267 | if confirmed.ID == tx.ID { |
| 268 | // confirmed |
| 269 | return height, nil |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | if tx.MaxTime > 0 && tx.MaxTime < b.TimestampMS { |
| 274 | return 0, errors.Wrap(txbuilder.ErrRejected, "transaction max time exceeded") |
| 275 | } |
| 276 | |
| 277 | // might still be in pool or might be rejected; we can't |
| 278 | // tell definitively until its max time elapses. |
| 279 | |
| 280 | // Re-insert into the pool in case it was dropped. |
| 281 | err = txbuilder.FinalizeTx(ctx, a.chain, a.submitter, tx) |
| 282 | if err != nil { |
| 283 | return 0, err |
| 284 | } |
| 285 | |
| 286 | // TODO(jackson): Do simple rejection checks like checking if |
| 287 | // the tx's blockchain prevouts still exist in the state tree. |
| 288 | } |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | type submitArg struct { |
| 293 | Transactions []txbuilder.Template |