Skip to content

Commit

Permalink
Merge pull request #135 from SiaFoundation/add-proof-output-id
Browse files Browse the repository at this point in the history
Add proof output IDs
  • Loading branch information
chris124567 authored Nov 8, 2024
2 parents 408dd43 + 718ad2b commit f5db0fe
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 62 deletions.
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

0 comments on commit f5db0fe

Please sign in to comment.