Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/account/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func utxoToInputs(ctx context.Context, account *signers.Signer, u *utxo, refData
*txbuilder.SigningInstruction,
error,
) {
txInput := bc.NewSpendInput(u.OutputID, nil, u.AssetID, u.Amount, u.ControlProgram, refData)
txInput := bc.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram, u.RefDataHash, refData)

sigInst := &txbuilder.SigningInstruction{
AssetAmount: u.AssetAmount,
Expand Down
12 changes: 6 additions & 6 deletions core/account/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestAccountSourceReserve(t *testing.T) {

accID = coretest.CreateAccount(ctx, t, accounts, "", nil)
asset = coretest.CreateAsset(ctx, t, assets, nil, "", nil)
txOut, outputID = coretest.IssueAssets(ctx, t, c, g, assets, accounts, asset, 2, accID)
txOut, txRes, _ = coretest.IssueAssets(ctx, t, c, g, assets, accounts, asset, 2, accID)
)

coretest.CreatePins(ctx, t, pinStore)
Expand All @@ -60,7 +60,7 @@ func TestAccountSourceReserve(t *testing.T) {
t.Fatal(err)
}

wantTxIns := []*bc.TxInput{bc.NewSpendInput(outputID, nil, txOut.AssetID, txOut.Amount, txOut.ControlProgram, nil)}
wantTxIns := []*bc.TxInput{bc.NewSpendInput(nil, txRes.SourceID, txOut.AssetID, txOut.Amount, txRes.SourcePos, txOut.ControlProgram, txRes.RefDataHash, nil)}
if !testutil.DeepEqual(tx.Inputs, wantTxIns) {
t.Errorf("build txins\ngot:\n\t%+v\nwant:\n\t%+v", tx.Inputs, wantTxIns)
}
Expand All @@ -86,9 +86,9 @@ func TestAccountSourceUTXOReserve(t *testing.T) {
assets = asset.NewRegistry(db, c, pinStore)
indexer = query.NewIndexer(db, c, pinStore)

accID = coretest.CreateAccount(ctx, t, accounts, "", nil)
asset = coretest.CreateAsset(ctx, t, assets, nil, "", nil)
txOut, outputID = coretest.IssueAssets(ctx, t, c, g, assets, accounts, asset, 2, accID)
accID = coretest.CreateAccount(ctx, t, accounts, "", nil)
asset = coretest.CreateAsset(ctx, t, assets, nil, "", nil)
txOut, txRes, outputID = coretest.IssueAssets(ctx, t, c, g, assets, accounts, asset, 2, accID)
)

coretest.CreatePins(ctx, t, pinStore)
Expand All @@ -111,7 +111,7 @@ func TestAccountSourceUTXOReserve(t *testing.T) {
t.Fatal(err)
}

wantTxIns := []*bc.TxInput{bc.NewSpendInput(outputID, nil, txOut.AssetID, txOut.Amount, txOut.ControlProgram, nil)}
wantTxIns := []*bc.TxInput{bc.NewSpendInput(nil, txRes.SourceID, txOut.AssetID, txOut.Amount, txRes.SourcePos, txOut.ControlProgram, txRes.RefDataHash, nil)}

if !testutil.DeepEqual(tx.Inputs, wantTxIns) {
t.Errorf("build txins\ngot:\n\t%+v\nwant:\n\t%+v", tx.Inputs, wantTxIns)
Expand Down
25 changes: 20 additions & 5 deletions core/account/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ type rawOutput struct {
ControlProgram []byte
txHash bc.Hash
outputIndex uint32
sourceID bc.Hash
sourcePos uint64
refData bc.Hash
}

type accountOutput struct {
Expand Down Expand Up @@ -121,6 +124,9 @@ func (m *Manager) indexAccountUTXOs(ctx context.Context, b *bc.Block) error {
ControlProgram: out.ControlProgram,
txHash: tx.ID,
outputIndex: uint32(j),
sourceID: tx.Results[j].SourceID,
sourcePos: tx.Results[j].SourcePos,
refData: tx.Results[j].RefDataHash,
}
outs = append(outs, out)
}
Expand All @@ -147,12 +153,11 @@ func (m *Manager) indexAccountUTXOs(ctx context.Context, b *bc.Block) error {

func prevoutDBKeys(txs ...*bc.Tx) (outputIDs pq.ByteaArray) {
for _, tx := range txs {
for _, in := range tx.Inputs {
for i, in := range tx.Inputs {
if in.IsIssuance() {
continue
}
o := in.SpentOutputID()
outputIDs = append(outputIDs, o.Bytes())
outputIDs = append(outputIDs, tx.SpentOutputIDs[i].Bytes())
}
}
return
Expand Down Expand Up @@ -208,6 +213,9 @@ func (m *Manager) upsertConfirmedAccountOutputs(ctx context.Context, outs []*acc
accountID pq.StringArray
cpIndex pq.Int64Array
program pq.ByteaArray
sourceID pq.ByteaArray
sourcePos pq.Int64Array
refData pq.ByteaArray
)
for _, out := range outs {
outputID = append(outputID, out.OutputID.Bytes())
Expand All @@ -216,13 +224,17 @@ func (m *Manager) upsertConfirmedAccountOutputs(ctx context.Context, outs []*acc
accountID = append(accountID, out.AccountID)
cpIndex = append(cpIndex, int64(out.keyIndex))
program = append(program, out.ControlProgram)
sourceID = append(sourceID, out.sourceID[:])
sourcePos = append(sourcePos, int64(out.sourcePos))
refData = append(refData, out.refData[:])
}

const q = `
INSERT INTO account_utxos (output_id, asset_id, amount, account_id, control_program_index,
control_program, confirmed_in)
control_program, confirmed_in, source_id, source_pos, ref_data_hash)
SELECT unnest($1::bytea[]), unnest($2::bytea[]), unnest($3::bigint[]),
unnest($4::text[]), unnest($5::bigint[]), unnest($6::bytea[]), $7
unnest($4::text[]), unnest($5::bigint[]), unnest($6::bytea[]), $7,
unnest($8::bytea[]), unnest($9::bigint[]), unnest($10::bytea[])
ON CONFLICT (output_id) DO NOTHING
`
_, err := m.db.Exec(ctx, q,
Expand All @@ -233,6 +245,9 @@ func (m *Manager) upsertConfirmedAccountOutputs(ctx context.Context, outs []*acc
cpIndex,
program,
block.Height,
sourceID,
sourcePos,
refData,
)
return errors.Wrap(err)
}
2 changes: 1 addition & 1 deletion core/account/indexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func TestDeleteUTXOs(t *testing.T) {
block2 := &bc.Block{Transactions: []*bc.Tx{
bc.NewTx(bc.TxData{
Inputs: []*bc.TxInput{
bc.NewSpendInput(tx.OutputID(0), nil, assetID, 1, nil, nil),
bc.NewSpendInput(nil, tx.Results[0].SourceID, assetID, 1, tx.Results[0].SourcePos, acp, tx.Results[0].RefDataHash, nil),
},
}),
}}
Expand Down
25 changes: 21 additions & 4 deletions core/account/reserve.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ var (
// utxo describes an individual account utxo.
type utxo struct {
OutputID bc.Hash
SourceID bc.Hash
bc.AssetAmount
SourcePos uint64
ControlProgram []byte
RefDataHash bc.Hash

AccountID string
ControlProgramIndex uint64
Expand Down Expand Up @@ -380,20 +383,24 @@ func (sr *sourceReserver) refillCache(ctx context.Context) error {

func findMatchingUTXOs(ctx context.Context, db pg.DB, src source, height uint64) ([]*utxo, error) {
const q = `
SELECT output_id, amount, control_program_index, control_program
SELECT output_id, amount, control_program_index, control_program,
source_id, source_pos, ref_data_hash
FROM account_utxos
WHERE account_id = $1 AND asset_id = $2 AND confirmed_in > $3
`
var utxos []*utxo
err := pg.ForQueryRows(ctx, db, q, src.AccountID, src.AssetID, height,
func(oid bc.Hash, amount uint64, cpIndex uint64, controlProg []byte) {
func(oid bc.Hash, amount uint64, cpIndex uint64, controlProg []byte, sourceID bc.Hash, sourcePos uint64, refData bc.Hash) {
utxos = append(utxos, &utxo{
OutputID: oid,
SourceID: sourceID,
AssetAmount: bc.AssetAmount{
Amount: amount,
AssetID: src.AssetID,
},
SourcePos: sourcePos,
ControlProgram: controlProg,
RefDataHash: refData,
AccountID: src.AccountID,
ControlProgramIndex: cpIndex,
})
Expand All @@ -406,13 +413,23 @@ func findMatchingUTXOs(ctx context.Context, db pg.DB, src source, height uint64)

func findSpecificUTXO(ctx context.Context, db pg.DB, out bc.Hash) (*utxo, error) {
const q = `
SELECT account_id, asset_id, amount, control_program_index, control_program
SELECT account_id, asset_id, amount, control_program_index, control_program,
source_id, source_pos, ref_data_hash
FROM account_utxos
WHERE output_id = $1
`
u := new(utxo)
// TODO(oleg): maybe we need to scan txid:index too from here...
err := db.QueryRow(ctx, q, out).Scan(&u.AccountID, &u.AssetID, &u.Amount, &u.ControlProgramIndex, &u.ControlProgram)
err := db.QueryRow(ctx, q, out).Scan(
&u.AccountID,
&u.AssetID,
&u.Amount,
&u.ControlProgramIndex,
&u.ControlProgram,
&u.SourceID,
&u.SourcePos,
&u.RefDataHash,
)
if err == sql.ErrNoRows {
return nil, pg.ErrUserInputNotFound
} else if err != nil {
Expand Down
6 changes: 4 additions & 2 deletions core/account/reserve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import (
const sampleAccountUTXOs = `
INSERT INTO account_utxos
(output_id, asset_id, amount, account_id, control_program_index,
control_program, confirmed_in) VALUES (
control_program, confirmed_in, source_id, source_pos, ref_data_hash) VALUES (
decode('9886ae2dc24b6d868c68768038c43801e905a62f1a9b826ca0dc357f00c30117', 'hex'),
decode('df1df9d4f66437ab5be715e4d1faeb29d24c80a6dc8276d6a630f05c5f1f7693', 'hex'),
1000, 'accEXAMPLE', 1, '\x6a'::bytea, 1);
1000, 'accEXAMPLE', 1, '\x6a'::bytea, 1,
decode('905a62f1a9b826ca0dc357f00c301179886ae2dc24b6d868c68768038c43801e', 'hex'),
0, decode('0000000000000000000000000000000000000000000000000000000000000000', 'hex'));
`

func TestCancelReservation(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions core/coretest/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func CreateAsset(ctx context.Context, t testing.TB, assets *asset.Registry, def
return asset.AssetID
}

func IssueAssets(ctx context.Context, t testing.TB, c *protocol.Chain, s txbuilder.Submitter, assets *asset.Registry, accounts *account.Manager, assetID bc.AssetID, amount uint64, accountID string) (*bc.TxOutput, bc.Hash) {
func IssueAssets(ctx context.Context, t testing.TB, c *protocol.Chain, s txbuilder.Submitter, assets *asset.Registry, accounts *account.Manager, assetID bc.AssetID, amount uint64, accountID string) (*bc.TxOutput, *bc.ResultInfo, bc.Hash) {
assetAmount := bc.AssetAmount{AssetID: assetID, Amount: amount}

tpl, err := txbuilder.Build(ctx, nil, []txbuilder.Action{
Expand All @@ -63,7 +63,7 @@ func IssueAssets(ctx context.Context, t testing.TB, c *protocol.Chain, s txbuild
testutil.FatalErr(t, err)
}

return tpl.Transaction.Outputs[0], tpl.Transaction.OutputID(0)
return tpl.Transaction.Outputs[0], &tpl.Transaction.Results[0], tpl.Transaction.OutputID(0)
}

func Transfer(ctx context.Context, t testing.TB, c *protocol.Chain, s txbuilder.Submitter, actions []txbuilder.Action) *bc.Tx {
Expand Down
6 changes: 6 additions & 0 deletions core/migrate/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,10 @@ var migrations = []migration{
DROP COLUMN index;
ALTER TABLE account_utxos ADD PRIMARY KEY (output_id);
`},
{Name: `2017-03-02.0.core.add-output-source-info.sql`, SQL: `
ALTER TABLE account_utxos
ADD COLUMN source_id bytea NOT NULL,
ADD COLUMN source_pos bigint NOT NULL,
ADD COLUMN ref_data_hash bytea NOT NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We expect customers to completely drop the database and recreate it before attempting to run a 1.1.1 binary right? I think that's a fine assumption when dealing with a blockchain reset.

Once landed, we should double check that the migration has the same name and hash on the 1.1.1 branch and main so that Cores updating from 1.1.1 to 1.2.0 do not try to run this migration again.

`},
}
9 changes: 5 additions & 4 deletions core/query/annotated.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,17 @@ func buildAnnotatedTransaction(orig *bc.Tx, b *bc.Block, indexInBlock uint32) *A
tx.ReferenceData = &referenceData
}

for _, in := range orig.Inputs {
tx.Inputs = append(tx.Inputs, buildAnnotatedInput(in))
for i := range orig.Inputs {
tx.Inputs = append(tx.Inputs, buildAnnotatedInput(orig, uint32(i)))
}
for i := range orig.Outputs {
tx.Outputs = append(tx.Outputs, buildAnnotatedOutput(orig, uint32(i)))
}
return tx
}

func buildAnnotatedInput(orig *bc.TxInput) *AnnotatedInput {
func buildAnnotatedInput(tx *bc.Tx, i uint32) *AnnotatedInput {
orig := tx.Inputs[i]
in := &AnnotatedInput{
AssetID: orig.AssetID(),
Amount: orig.Amount(),
Expand All @@ -158,7 +159,7 @@ func buildAnnotatedInput(orig *bc.TxInput) *AnnotatedInput {
in.Type = "issue"
in.IssuanceProgram = prog
} else {
prevoutID := orig.SpentOutputID()
prevoutID := tx.SpentOutputIDs[i]
in.Type = "spend"
in.ControlProgram = orig.ControlProgram()
in.SpentOutputID = &prevoutID
Expand Down
5 changes: 2 additions & 3 deletions core/query/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,9 @@ func (ind *Indexer) insertAnnotatedOutputs(ctx context.Context, b *bc.Block, ann
prevoutIDs pq.ByteaArray
)
for pos, tx := range b.Transactions {
for _, in := range tx.Inputs {
for i, in := range tx.Inputs {
if !in.IsIssuance() {
prevoutID := in.SpentOutputID()
prevoutIDs = append(prevoutIDs, prevoutID.Bytes())
prevoutIDs = append(prevoutIDs, tx.SpentOutputIDs[i].Bytes())
}
}

Expand Down
6 changes: 5 additions & 1 deletion core/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ CREATE TABLE account_utxos (
control_program_index bigint NOT NULL,
control_program bytea NOT NULL,
confirmed_in bigint NOT NULL,
output_id bytea NOT NULL
output_id bytea NOT NULL,
source_id bytea NOT NULL,
source_pos bigint NOT NULL,
ref_data_hash bytea NOT NULL
);


Expand Down Expand Up @@ -895,3 +898,4 @@ insert into migrations (filename, hash) values ('2017-02-03.0.core.schema-snapsh
insert into migrations (filename, hash) values ('2017-02-07.0.query.non-null-alias.sql', '17028a0bdbc95911e299dc65fe641184e54c87a0d07b3c576d62d023b9a8defc');
insert into migrations (filename, hash) values ('2017-02-16.0.query.spent-output.sql', '7cd52095b6f202d7a25ffe666b7b7d60e7700d314a7559b911e236b72661a738');
insert into migrations (filename, hash) values ('2017-02-28.0.core.remove-outpoints.sql', '067638e2a826eac70d548f2d6bb234660f3200064072baf42db741456ecf8deb');
insert into migrations (filename, hash) values ('2017-03-02.0.core.add-output-source-info.sql', 'f44c7cfbff346f6f797d497910c0a76f2a7600ca8b5be4fe4e4a04feaf32e0df');
Loading