Skip to content
This repository has been archived by the owner on Nov 2, 2018. It is now read-only.

Commit

Permalink
Merge pull request #2923 from nielscastien/contract-api
Browse files Browse the repository at this point in the history
Create API endpoint to retrieve contract information on host
  • Loading branch information
lukechampine committed Apr 17, 2018
2 parents 892f535 + a198546 commit 8533b8c
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 27 deletions.
40 changes: 38 additions & 2 deletions doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ Host
| [/host](#host-get) | GET |
| [/host](#host-post) | POST |
| [/host/announce](#hostannounce-post) | POST |
| [/host/contracts](#hostcontracts-get) | GET |
| [/host/estimatescore](#hostestimatescore-get) | GET |
| [/host/storage](#hoststorage-get) | GET |
| [/host/storage/folders/add](#hoststoragefoldersadd-post) | POST |
Expand Down Expand Up @@ -408,11 +409,46 @@ netaddress string // Optional
standard success or error response. See
[#standard-responses](#standard-responses).

#### /host/contracts [GET]

gets a list of all contracts from the host database

###### JSON Response [(with comments)](/doc/api/Host.md#json-response-1)
```javascript
{
"contracts": [
{
"contractcost": "1234", // hastings
"datasize": 500000, // bytes
"lockedcollateral": "1234", // hastings
"obligationid": "fff48010dcbbd6ba7ffd41bc4b25a3634ee58bbf688d2f06b7d5a0c837304e13",
"potentialdownloadrevenue": "1234", // hastings
"potentialstoragerevenue": "1234", // hastings
"potentialuploadrevenue": "1234", // hastings
"riskedcollateral": "1234", // hastings
"sectorrootscount": 2,
"transactionfeesadded": "1234", // hastings

"expirationheight": 123456, // blocks
"negotiationheight": 123456, // blocks
"proofdeadline": 123456, // blocks

"obligationstatus": "obligationFailed",
"originconfirmed": true,
"proofconfirmed": true,
"proofconstructed": true
"revisionconfirmed": false,
"revisionconstructed": false,
}
]
}
```

#### /host/storage [GET]

gets a list of folders tracked by the host's storage manager.

###### JSON Response [(with comments)](/doc/api/Host.md#json-response-1)
###### JSON Response [(with comments)](/doc/api/Host.md#json-response-2)
```javascript
{
"folders": [
Expand Down Expand Up @@ -503,7 +539,7 @@ standard success or error response. See
returns the estimated HostDB score of the host using its current settings,
combined with the provided settings.

###### JSON Response [(with comments)](/doc/api/Host.md#json-response-2)
###### JSON Response [(with comments)](/doc/api/Host.md#json-response-3)
```javascript
{
"estimatedscore": "123456786786786786786786786742133",
Expand Down
73 changes: 73 additions & 0 deletions doc/api/Host.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Index
| [/host](#host-get) | GET |
| [/host](#host-post) | POST |
| [/host/announce](#hostannounce-post) | POST |
| [/host/contracts](#hostcontracts-get) | GET |
| [/host/estimatescore](#hostestimatescore-get) | GET |
| [/host/storage](#hoststorage-get) | GET |
| [/host/storage/folders/add](#hoststoragefoldersadd-post) | POST |
Expand Down Expand Up @@ -432,6 +433,78 @@ netaddress string // Optional
standard success or error response. See
[#standard-responses](#standard-responses).

#### /host/contracts [GET]

Get contract information from the host database. This call will return all storage obligations on the host. Its up to the caller to filter the contracts based on his needs.

###### JSON Response
```javascript
{
"contracts": [
// Amount in hastings to cover the transaction fees for this storage obligation.
"contractcost": "1234", // hastings

// Size of the data that is protected by the contract.
"datasize": 50000, // bytes

// Amount that is locked as collateral for this storage obligation.
"lockedcollateral": "1234", // hastings

// Id of the storageobligation, which is defined by the file contract id of the file contract that governs the storage obligation.
"obligationid": "fff48010dcbbd6ba7ffd41bc4b25a3634ee58bbf688d2f06b7d5a0c837304e13",

// Potential revenue for downloaded data that the host will reveive upon successful completion of the obligation.
"potentialdownloadrevenue": "1234", // hastings

// Potential revenue for storage of data that the host will reveive upon successful completion of the obligation.
"potentialstoragerevenue": "1234", // hastings

// Potential revenue for uploaded data that the host will reveive upon successful completion of the obligation.
"potentialuploadrevenue": "1234", // hastings

// Amount that the host might lose if the submission of the storage proof is not successful.
"riskedcollateral": "1234", // hastings

// Number of sector roots.
"sectorrootscount": 2,

// Amount for transaction fees that the host added to the storage obligation.
"transactionfeesadded": "1234", // hastings

// Experation height is the height at which the storage obligation expires.
"expirationheight": 123456, // blocks

// Negotion height is the height at which the storage obligation was negotiated.
"negotiationheight": 0, // blocks

// The proof deadline is the height by which the storage proof must be submitted.
"proofdeadline": 123456, // blocks

// Status of the storage obligation. There are 4 different statuses:
// obligationFailed: the storage obligation failed, potential revenues and risked collateral are lost
// obligationRejected: the storage obligation was never started, no revenues gained or lost
// obligationSucceeded: the storage obligation was completed, revenues were gained
// obligationUnresolved: the storage obligation has an uninitialized value. When the "proofdeadline" is in the past this might be a stale obligation.
"obligationstatus": "obligationFailed",

// Origin confirmed indicates whether the file contract was seen on the blockchain for this storage obligation.
"originconfirmed": true,

// Proof confirmed indicates whether there was a storage proof seen on the blockchain for this storage obligation.
"proofconfirmed": true,

// The host has constructed a storage proof
"proofconstructed": false

// Revision confirmed indicates whether there was a file contract revision seen on the blockchain for this storage obligation.
"revisionconfirmed": true,

// Revision constructed indicates whether there was a file contract revision constructed for this storage obligation.
"revisionconstructed": true,
]
}
```

#### /host/storage [GET]

gets a list of folders tracked by the host's storage manager.
Expand Down
27 changes: 23 additions & 4 deletions modules/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,33 @@ type (
// StorageObligation contains information about a storage obligation that
// the host has accepted.
StorageObligation struct {
ContractCost types.Currency `json:"contractcost"`
DataSize uint64 `json:"datasize"`
LockedCollateral types.Currency `json:"lockedcollateral"`
ObligationId types.FileContractID `json:"obligationid"`
PotentialDownloadRevenue types.Currency `json:"potentialdownloadrevenue"`
PotentialStorageRevenue types.Currency `json:"potentialstoragerevenue"`
PotentialUploadRevenue types.Currency `json:"potentialuploadrevenue"`
RiskedCollateral types.Currency `json:"riskedcollateral"`
SectorRootsCount uint64 `json:"sectorrootscount"`
TransactionFeesAdded types.Currency `json:"transactionfeesadded"`

// The negotiation height specifies the block height at which the file
// contract was negotiated. The expiration height and the proof deadline
// are equal to the window start and window end. Between the expiration height
// and the proof deadline, the host must submit the storage proof.
ExpirationHeight types.BlockHeight `json:"expirationheight"`
NegotiationHeight types.BlockHeight `json:"negotiationheight"`
ProofDeadLine types.BlockHeight `json:"proofdeadline"`

// Variables indicating whether the critical transactions in a storage
// obligation have been confirmed on the blockchain.
ObligationStatus string `json:"obligationstatus"`
OriginConfirmed bool `json:"originconfirmed"`
RevisionConstructed bool `json:"revisionconstructed"`
RevisionConfirmed bool `json:"revisionconfirmed"`
ProofConstructed bool `json:"proofconstructed"`
ProofConfirmed bool `json:"proofconfirmed"`
ObligationStatus uint64 `json:"obligationstatus"`
ProofConstructed bool `json:"proofconstructed"`
RevisionConfirmed bool `json:"revisionconfirmed"`
RevisionConstructed bool `json:"revisionconstructed"`
}

// HostWorkingStatus reports the working state of a host. Can be one of
Expand Down
49 changes: 41 additions & 8 deletions modules/host/storageobligations.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@ package host

// TODO: Make sure that not too many action items are being created.

// TODO: The ProofConstructed and NegotiationHeight fields of storageObligation
// are not set or used.

import (
"encoding/binary"
"encoding/json"
"errors"
"strconv"

"github.com/NebulousLabs/Sia/build"
"github.com/NebulousLabs/Sia/crypto"
Expand Down Expand Up @@ -139,12 +143,28 @@ type storageObligation struct {

// Variables indicating whether the critical transactions in a storage
// obligation have been confirmed on the blockchain.
ObligationStatus storageObligationStatus
OriginConfirmed bool
RevisionConstructed bool
RevisionConfirmed bool
ProofConstructed bool
ProofConfirmed bool
ObligationStatus storageObligationStatus
ProofConstructed bool
RevisionConfirmed bool
RevisionConstructed bool
}

func (i storageObligationStatus) String() string {
if i == 0 {
return "obligationUnresolved"
}
if i == 1 {
return "obligationRejected"
}
if i == 2 {
return "obligationSucceeded"
}
if i == 3 {
return "obligationFailed"
}
return "storageObligationStatus(" + strconv.FormatInt(int64(i), 10) + ")"
}

// getStorageObligation fetches a storage obligation from the database tx.
Expand Down Expand Up @@ -870,14 +890,27 @@ func (h *Host) StorageObligations() (sos []modules.StorageObligation) {
return build.ExtendErr("unable to unmarshal storage obligation:", err)
}
mso := modules.StorageObligation{
ContractCost: so.ContractCost,
DataSize: so.fileSize(),
LockedCollateral: so.LockedCollateral,
ObligationId: so.id(),
PotentialDownloadRevenue: so.PotentialDownloadRevenue,
PotentialStorageRevenue: so.PotentialStorageRevenue,
PotentialUploadRevenue: so.PotentialUploadRevenue,
RiskedCollateral: so.RiskedCollateral,
SectorRootsCount: uint64(len(so.SectorRoots)),
TransactionFeesAdded: so.TransactionFeesAdded,

ExpirationHeight: so.expiration(),
NegotiationHeight: so.NegotiationHeight,
ProofDeadLine: so.proofDeadline(),

ObligationStatus: so.ObligationStatus.String(),
OriginConfirmed: so.OriginConfirmed,
RevisionConstructed: so.RevisionConstructed,
RevisionConfirmed: so.RevisionConfirmed,
ProofConstructed: so.ProofConstructed,
ProofConfirmed: so.ProofConfirmed,
ObligationStatus: uint64(so.ObligationStatus),
ProofConstructed: so.ProofConstructed,
RevisionConfirmed: so.RevisionConfirmed,
RevisionConstructed: so.RevisionConstructed,
}
sos = append(sos, mso)
return nil
Expand Down
15 changes: 15 additions & 0 deletions node/api/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ var (
)

type (
// ContractInfoGET contains the information that is returned after a GET request
// to /host/contracts - information for the host about stored obligations.
ContractInfoGET struct {
Contracts []modules.StorageObligation `json:"contracts"`
}

// HostGET contains the information that is returned after a GET request to
// /host - a bunch of information about the status of the host.
HostGET struct {
Expand Down Expand Up @@ -61,6 +67,15 @@ func folderIndex(folderPath string, storageFolders []modules.StorageFolderMetada
return -1, errStorageFolderNotFound
}

// hostContractInfoHandler handles the API call to get the contract information of the host.
// Information is retrieved via the storage obligations from the host database.
func (api *API) hostContractInfoHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
cg := ContractInfoGET{
Contracts: api.host.StorageObligations(),
}
WriteJSON(w, cg)
}

// hostHandlerGET handles GET requests to the /host API endpoint, returning key
// information about the host.
func (api *API) hostHandlerGET(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
Expand Down
Loading

0 comments on commit 8533b8c

Please sign in to comment.