| 284 | } |
| 285 | |
| 286 | func (m *Manager) insertAccountControlProgram(ctx context.Context, progs ...*controlProgram) error { |
| 287 | const q = ` |
| 288 | INSERT INTO account_control_programs (signer_id, key_index, control_program, change, expires_at) |
| 289 | SELECT unnest($1::text[]), unnest($2::bigint[]), unnest($3::bytea[]), unnest($4::boolean[]), |
| 290 | unnest($5::timestamp with time zone[]) |
| 291 | ` |
| 292 | var ( |
| 293 | accountIDs pq.StringArray |
| 294 | keyIndexes pq.Int64Array |
| 295 | controlProgs pq.ByteaArray |
| 296 | change pq.BoolArray |
| 297 | expirations []stdsql.NullString |
| 298 | ) |
| 299 | for _, p := range progs { |
| 300 | accountIDs = append(accountIDs, p.accountID) |
| 301 | keyIndexes = append(keyIndexes, int64(p.keyIndex)) |
| 302 | controlProgs = append(controlProgs, p.controlProgram) |
| 303 | change = append(change, p.change) |
| 304 | expirations = append(expirations, stdsql.NullString{ |
| 305 | String: p.expiresAt.Format(time.RFC3339), |
| 306 | Valid: !p.expiresAt.IsZero(), |
| 307 | }) |
| 308 | } |
| 309 | |
| 310 | _, err := m.db.Exec(ctx, q, accountIDs, keyIndexes, controlProgs, change, pq.Array(expirations)) |
| 311 | return errors.Wrap(err) |
| 312 | } |
| 313 | |
| 314 | func (m *Manager) nextIndex(ctx context.Context) (uint64, error) { |
| 315 | m.acpMu.Lock() |