Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add proof output IDs #135

Merged
merged 4 commits into from
Nov 8, 2024
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
8 changes: 4 additions & 4 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,26 +186,26 @@ func (c *Client) AddressBalance(address types.Address) (resp AddressBalanceRespo
}

// Contract returns the file contract with the specified ID.
func (c *Client) Contract(id types.FileContractID) (resp explorer.FileContract, err error) {
func (c *Client) Contract(id types.FileContractID) (resp explorer.ExtendedFileContract, err error) {
err = c.c.GET(fmt.Sprintf("/contracts/%s", id), &resp)
return
}

// Contracts returns the transactions with the specified IDs.
func (c *Client) Contracts(ids []types.FileContractID) (resp []explorer.FileContract, err error) {
func (c *Client) Contracts(ids []types.FileContractID) (resp []explorer.ExtendedFileContract, err error) {
err = c.c.POST("/contracts", ids, &resp)
return
}

// ContractsKey returns the contracts for a particular ed25519 key.
func (c *Client) ContractsKey(key types.PublicKey) (resp []explorer.FileContract, err error) {
func (c *Client) ContractsKey(key types.PublicKey) (resp []explorer.ExtendedFileContract, err error) {
err = c.c.GET(fmt.Sprintf("/pubkey/%s/contracts", key), &resp)
return
}

// ContractRevisions returns all the revisions of the contract with the
// specified ID.
func (c *Client) ContractRevisions(id types.FileContractID) (resp []explorer.FileContract, err error) {
func (c *Client) ContractRevisions(id types.FileContractID) (resp []explorer.ExtendedFileContract, err error) {
err = c.c.GET(fmt.Sprintf("/contracts/%s/revisions", id), &resp)
return
}
Expand Down
6 changes: 3 additions & 3 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ type (
UnspentSiacoinOutputs(address types.Address, offset, limit uint64) ([]explorer.SiacoinOutput, error)
UnspentSiafundOutputs(address types.Address, offset, limit uint64) ([]explorer.SiafundOutput, error)
AddressEvents(address types.Address, offset, limit uint64) (events []explorer.Event, err error)
Contracts(ids []types.FileContractID) (result []explorer.FileContract, err error)
ContractsKey(key types.PublicKey) (result []explorer.FileContract, err error)
ContractRevisions(id types.FileContractID) (result []explorer.FileContract, err error)
Contracts(ids []types.FileContractID) (result []explorer.ExtendedFileContract, err error)
ContractsKey(key types.PublicKey) (result []explorer.ExtendedFileContract, err error)
ContractRevisions(id types.FileContractID) (result []explorer.ExtendedFileContract, err error)
Search(id types.Hash256) (explorer.SearchType, error)

Hosts(pks []types.PublicKey) ([]explorer.Host, error)
Expand Down
12 changes: 6 additions & 6 deletions explorer/explorer.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ type Store interface {
UnspentSiafundOutputs(address types.Address, offset, limit uint64) ([]SiafundOutput, error)
AddressEvents(address types.Address, offset, limit uint64) (events []Event, err error)
Balance(address types.Address) (sc types.Currency, immatureSC types.Currency, sf uint64, err error)
Contracts(ids []types.FileContractID) (result []FileContract, err error)
ContractsKey(key types.PublicKey) (result []FileContract, err error)
ContractRevisions(id types.FileContractID) (result []FileContract, err error)
Contracts(ids []types.FileContractID) (result []ExtendedFileContract, err error)
ContractsKey(key types.PublicKey) (result []ExtendedFileContract, err error)
ContractRevisions(id types.FileContractID) (result []ExtendedFileContract, err error)
SiacoinElements(ids []types.SiacoinOutputID) (result []SiacoinOutput, err error)
SiafundElements(ids []types.SiafundOutputID) (result []SiafundOutput, err error)

Expand Down Expand Up @@ -247,18 +247,18 @@ func (e *Explorer) Balance(address types.Address) (sc types.Currency, immatureSC
}

// Contracts returns the contracts with the specified IDs.
func (e *Explorer) Contracts(ids []types.FileContractID) (result []FileContract, err error) {
func (e *Explorer) Contracts(ids []types.FileContractID) (result []ExtendedFileContract, err error) {
return e.s.Contracts(ids)
}

// ContractsKey returns the contracts for a particular ed25519 key.
func (e *Explorer) ContractsKey(key types.PublicKey) (result []FileContract, err error) {
func (e *Explorer) ContractsKey(key types.PublicKey) (result []ExtendedFileContract, err error) {
return e.s.ContractsKey(key)
}

// ContractRevisions returns all the revisions of the contract with the
// specified ID.
func (e *Explorer) ContractRevisions(id types.FileContractID) (result []FileContract, err error) {
func (e *Explorer) ContractRevisions(id types.FileContractID) (result []ExtendedFileContract, err error) {
return e.s.ContractRevisions(id)
}

Expand Down
33 changes: 28 additions & 5 deletions explorer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,32 @@ type SiafundOutput struct {
types.SiafundElement
}

// A FileContract is a types.FileContractElement with added fields for
// resolved/valid state.
// A ContractSiacoinOutput is a SiacoinOutput with an added field for its ID.
type ContractSiacoinOutput struct {
ID types.SiacoinOutputID `json:"id"`
types.SiacoinOutput
}

// A FileContract is a storage agreement between a renter and a host. It
// serves as a bidirectional payment channel that resolves as either "valid"
// or "missed" depending on whether a valid StorageProof is submitted for the
// contract.
type FileContract struct {
ID types.FileContractID `json:"id"`
Filesize uint64 `json:"filesize"`
FileMerkleRoot types.Hash256 `json:"fileMerkleRoot"`
WindowStart uint64 `json:"windowStart"`
WindowEnd uint64 `json:"windowEnd"`
Payout types.Currency `json:"payout"`
ValidProofOutputs []ContractSiacoinOutput `json:"validProofOutputs"`
MissedProofOutputs []ContractSiacoinOutput `json:"missedProofOutputs"`
UnlockHash types.Hash256 `json:"unlockHash"`
RevisionNumber uint64 `json:"revisionNumber"`
}

// A ExtendedFileContract is a FileContract with added fields for
// resolved/valid state, and when the transaction was confirmed and proved.
type ExtendedFileContract struct {
Resolved bool `json:"resolved"`
Valid bool `json:"valid"`

Expand All @@ -137,7 +160,7 @@ type FileContract struct {
ProofIndex *types.ChainIndex `json:"proofIndex"`
ProofTransactionID *types.TransactionID `json:"proofTransactionID"`

types.FileContractElement
FileContract
}

// A FileContractRevision is a FileContract with extra fields for revision
Expand All @@ -146,7 +169,7 @@ type FileContractRevision struct {
ParentID types.FileContractID `json:"parentID"`
UnlockConditions types.UnlockConditions `json:"unlockConditions"`

FileContract
ExtendedFileContract
}

// A Transaction is a transaction that uses the wrapped types above.
Expand All @@ -156,7 +179,7 @@ type Transaction struct {
SiacoinOutputs []SiacoinOutput `json:"siacoinOutputs,omitempty"`
SiafundInputs []SiafundInput `json:"siafundInputs,omitempty"`
SiafundOutputs []SiafundOutput `json:"siafundOutputs,omitempty"`
FileContracts []FileContract `json:"fileContracts,omitempty"`
FileContracts []ExtendedFileContract `json:"fileContracts,omitempty"`
FileContractRevisions []FileContractRevision `json:"fileContractRevisions,omitempty"`
StorageProofs []types.StorageProof `json:"storageProofs,omitempty"`
MinerFees []types.Currency `json:"minerFees,omitempty"`
Expand Down
2 changes: 1 addition & 1 deletion internal/testutil/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func CheckV2ChainIndices(t *testing.T, db explorer.Store, txnID types.Transactio

// CheckFC checks the retrieved file contract with the source file contract in
// addition to checking the resolved and valid fields.
func CheckFC(t *testing.T, revision, resolved, valid bool, expected types.FileContract, got explorer.FileContract) {
func CheckFC(t *testing.T, revision, resolved, valid bool, expected types.FileContract, got explorer.ExtendedFileContract) {
t.Helper()

Equal(t, "resolved state", resolved, got.Resolved)
Expand Down
8 changes: 4 additions & 4 deletions persist/sqlite/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,13 +790,13 @@ func updateFileContractElements(tx *txn, revert bool, b types.Block, fces []expl
}
defer revisionStmt.Close()

validOutputsStmt, err := tx.Prepare(`INSERT INTO file_contract_valid_proof_outputs(contract_id, contract_order, address, value) VALUES (?, ?, ?, ?) ON CONFLICT DO NOTHING`)
validOutputsStmt, err := tx.Prepare(`INSERT INTO file_contract_valid_proof_outputs(contract_id, contract_order, id, address, value) VALUES (?, ?, ?, ?, ?) ON CONFLICT DO NOTHING`)
if err != nil {
return nil, fmt.Errorf("addFileContracts: failed to prepare valid proof outputs statement: %w", err)
}
defer validOutputsStmt.Close()

missedOutputsStmt, err := tx.Prepare(`INSERT INTO file_contract_missed_proof_outputs(contract_id, contract_order, address, value) VALUES (?, ?, ?, ?) ON CONFLICT DO NOTHING`)
missedOutputsStmt, err := tx.Prepare(`INSERT INTO file_contract_missed_proof_outputs(contract_id, contract_order, id, address, value) VALUES (?, ?, ?, ?, ?) ON CONFLICT DO NOTHING`)
if err != nil {
return nil, fmt.Errorf("addFileContracts: failed to prepare missed proof outputs statement: %w", err)
}
Expand Down Expand Up @@ -861,12 +861,12 @@ func updateFileContractElements(tx *txn, revert bool, b types.Block, fces []expl
}

for i, sco := range fc.ValidProofOutputs {
if _, err := validOutputsStmt.Exec(dbID, i, encode(sco.Address), encode(sco.Value)); err != nil {
if _, err := validOutputsStmt.Exec(dbID, i, encode(fcID.ValidOutputID(i)), encode(sco.Address), encode(sco.Value)); err != nil {
return fmt.Errorf("updateFileContractElements: failed to execute valid proof outputs statement: %w", err)
}
}
for i, sco := range fc.MissedProofOutputs {
if _, err := missedOutputsStmt.Exec(dbID, i, encode(sco.Address), encode(sco.Value)); err != nil {
if _, err := missedOutputsStmt.Exec(dbID, i, encode(fcID.MissedOutputID(i)), encode(sco.Address), encode(sco.Value)); err != nil {
return fmt.Errorf("updateFileContractElements: failed to execute missed proof outputs statement: %w", err)
}
}
Expand Down
36 changes: 27 additions & 9 deletions persist/sqlite/consensus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,34 @@ func CheckChainIndices(t *testing.T, db explorer.Store, txnID types.TransactionI
}

// CheckFCRevisions checks that the revision numbers for the file contracts match.
func CheckFCRevisions(t *testing.T, confirmationIndex types.ChainIndex, confirmationTransactionID types.TransactionID, valid, missed []types.SiacoinOutput, revisionNumbers []uint64, fcs []explorer.FileContract) {
func CheckFCRevisions(t *testing.T, confirmationIndex types.ChainIndex, confirmationTransactionID types.TransactionID, valid, missed []types.SiacoinOutput, revisionNumbers []uint64, fcs []explorer.ExtendedFileContract) {
t.Helper()

testutil.Equal(t, "number of revisions", len(revisionNumbers), len(fcs))
for i := range revisionNumbers {
testutil.Equal(t, "revision number", revisionNumbers[i], fcs[i].FileContract.RevisionNumber)
testutil.Equal(t, "confirmation index", confirmationIndex, *fcs[i].ConfirmationIndex)
testutil.Equal(t, "confirmation transaction ID", confirmationTransactionID, *fcs[i].ConfirmationTransactionID)
testutil.Equal(t, "valid proof outputs", valid, fcs[i].FileContract.ValidProofOutputs)
testutil.Equal(t, "missed proof outputs", missed, fcs[i].FileContract.MissedProofOutputs)
testutil.Equal(t, "revision number", revisionNumbers[i], fcs[i].FileContract.RevisionNumber)

testutil.Equal(t, "valid proof outputs", len(valid), len(fcs[i].FileContract.ValidProofOutputs))
for j := range valid {
expected := valid[j]
got := fcs[i].FileContract.ValidProofOutputs[j]

testutil.Equal(t, "id", fcs[i].ID.ValidOutputID(j), got.ID)
testutil.Equal(t, "value", expected.Value, got.Value)
testutil.Equal(t, "address", expected.Address, got.Address)
}

testutil.Equal(t, "missed proof outputs", len(missed), len(fcs[i].FileContract.MissedProofOutputs))
for j := range missed {
expected := missed[j]
got := fcs[i].FileContract.MissedProofOutputs[j]

testutil.Equal(t, "id", fcs[i].ID.MissedOutputID(j), got.ID)
testutil.Equal(t, "value", expected.Value, got.Value)
testutil.Equal(t, "address", expected.Address, got.Address)
}
}
}

Expand Down Expand Up @@ -697,7 +715,7 @@ func TestFileContract(t *testing.T) {
testutil.Equal(t, "confirmation index", prevTip, *fcr.ConfirmationIndex)
testutil.Equal(t, "confirmation transaction ID", txn.ID(), *fcr.ConfirmationTransactionID)

testutil.CheckFC(t, false, false, false, fc, fcr.FileContract)
testutil.CheckFC(t, false, false, false, fc, fcr.ExtendedFileContract)
}

for i := cm.Tip().Height; i < windowEnd; i++ {
Expand Down Expand Up @@ -920,7 +938,7 @@ func TestEphemeralFileContract(t *testing.T) {
testutil.Equal(t, "parent id", txn.FileContractID(0), fcr.ParentID)
testutil.Equal(t, "unlock conditions", uc, fcr.UnlockConditions)

testutil.CheckFC(t, true, false, false, revisedFC1, fcr.FileContract)
testutil.CheckFC(t, true, false, false, revisedFC1, fcr.ExtendedFileContract)
}

revisedFC2 := revisedFC1
Expand Down Expand Up @@ -1002,7 +1020,7 @@ func TestEphemeralFileContract(t *testing.T) {
fcr := txns[0].FileContractRevisions[0]
testutil.Equal(t, "parent id", txn.FileContractID(0), fcr.ParentID)
testutil.Equal(t, "unlock conditions", uc, fcr.UnlockConditions)
testutil.CheckFC(t, true, false, false, revisedFC2, fcr.FileContract)
testutil.CheckFC(t, true, false, false, revisedFC2, fcr.ExtendedFileContract)
}

{
Expand All @@ -1016,7 +1034,7 @@ func TestEphemeralFileContract(t *testing.T) {
fcr := txns[0].FileContractRevisions[0]
testutil.Equal(t, "parent id", txn.FileContractID(0), fcr.ParentID)
testutil.Equal(t, "unlock conditions", uc, fcr.UnlockConditions)
testutil.CheckFC(t, true, false, false, revisedFC3, fcr.FileContract)
testutil.CheckFC(t, true, false, false, revisedFC3, fcr.ExtendedFileContract)
}
}

Expand Down Expand Up @@ -2330,7 +2348,7 @@ func TestMultipleReorgFileContract(t *testing.T) {
testutil.Equal(t, "parent id", txn.FileContractID(0), fcr.ParentID)
testutil.Equal(t, "unlock conditions", uc, fcr.UnlockConditions)

testutil.CheckFC(t, false, false, false, revFC, fcr.FileContract)
testutil.CheckFC(t, false, false, false, revFC, fcr.ExtendedFileContract)
}

{
Expand Down
Loading
Loading