github.com/ZuluSpl0it/Sia@v1.3.7/node/api/consensus.go (about)

     1  package api
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/NebulousLabs/Sia/crypto"
     9  	"github.com/NebulousLabs/Sia/types"
    10  
    11  	"github.com/julienschmidt/httprouter"
    12  )
    13  
    14  // ConsensusGET contains general information about the consensus set, with tags
    15  // to support idiomatic json encodings.
    16  type ConsensusGET struct {
    17  	Synced       bool              `json:"synced"`
    18  	Height       types.BlockHeight `json:"height"`
    19  	CurrentBlock types.BlockID     `json:"currentblock"`
    20  	Target       types.Target      `json:"target"`
    21  	Difficulty   types.Currency    `json:"difficulty"`
    22  }
    23  
    24  // ConsensusHeadersGET contains information from a blocks header.
    25  type ConsensusHeadersGET struct {
    26  	BlockID types.BlockID `json:"blockid"`
    27  }
    28  
    29  // ConsensusBlocksGet contains all fields of a types.Block and additional
    30  // fields for ID and Height.
    31  type ConsensusBlocksGet struct {
    32  	ID           types.BlockID           `json:"id"`
    33  	Height       types.BlockHeight       `json:"height"`
    34  	ParentID     types.BlockID           `json:"parentid"`
    35  	Nonce        types.BlockNonce        `json:"nonce"`
    36  	Timestamp    types.Timestamp         `json:"timestamp"`
    37  	MinerPayouts []types.SiacoinOutput   `json:"minerpayouts"`
    38  	Transactions []ConsensusBlocksGetTxn `json:"transactions"`
    39  }
    40  
    41  // ConsensusBlocksGetTxn contains all fields of a types.Transaction and an
    42  // additional ID field.
    43  type ConsensusBlocksGetTxn struct {
    44  	ID                    types.TransactionID               `json:"id"`
    45  	SiacoinInputs         []types.SiacoinInput              `json:"siacoininputs"`
    46  	SiacoinOutputs        []ConsensusBlocksGetSiacoinOutput `json:"siacoinoutputs"`
    47  	FileContracts         []ConsensusBlocksGetFileContract  `json:"filecontracts"`
    48  	FileContractRevisions []types.FileContractRevision      `json:"filecontractrevisions"`
    49  	StorageProofs         []types.StorageProof              `json:"storageproofs"`
    50  	SiafundInputs         []types.SiafundInput              `json:"siafundinputs"`
    51  	SiafundOutputs        []ConsensusBlocksGetSiafundOutput `json:"siafundoutputs"`
    52  	MinerFees             []types.Currency                  `json:"minerfees"`
    53  	ArbitraryData         [][]byte                          `json:"arbitrarydata"`
    54  	TransactionSignatures []types.TransactionSignature      `json:"transactionsignatures"`
    55  }
    56  
    57  // ConsensusBlocksGetFileContract contains all fields of a types.FileContract
    58  // and an additional ID field.
    59  type ConsensusBlocksGetFileContract struct {
    60  	ID                 types.FileContractID              `json:"id"`
    61  	FileSize           uint64                            `json:"filesize"`
    62  	FileMerkleRoot     crypto.Hash                       `json:"filemerkleroot"`
    63  	WindowStart        types.BlockHeight                 `json:"windowstart"`
    64  	WindowEnd          types.BlockHeight                 `json:"windowend"`
    65  	Payout             types.Currency                    `json:"payout"`
    66  	ValidProofOutputs  []ConsensusBlocksGetSiacoinOutput `json:"validproofoutputs"`
    67  	MissedProofOutputs []ConsensusBlocksGetSiacoinOutput `json:"missedproofoutputs"`
    68  	UnlockHash         types.UnlockHash                  `json:"unlockhash"`
    69  	RevisionNumber     uint64                            `json:"revisionnumber"`
    70  }
    71  
    72  // ConsensusBlocksGetSiacoinOutput contains all fields of a types.SiacoinOutput
    73  // and an additional ID field.
    74  type ConsensusBlocksGetSiacoinOutput struct {
    75  	ID         types.SiacoinOutputID `json:"id"`
    76  	Value      types.Currency        `json:"value"`
    77  	UnlockHash types.UnlockHash      `json:"unlockhash"`
    78  }
    79  
    80  // ConsensusBlocksGetSiafundOutput contains all fields of a types.SiafundOutput
    81  // and an additional ID field.
    82  type ConsensusBlocksGetSiafundOutput struct {
    83  	ID         types.SiafundOutputID `json:"id"`
    84  	Value      types.Currency        `json:"value"`
    85  	UnlockHash types.UnlockHash      `json:"unlockhash"`
    86  }
    87  
    88  // ConsensusBlocksGetFromBlock is a helper method that uses a types.Block and
    89  // types.BlockHeight to create a ConsensusBlocksGet object.
    90  func consensusBlocksGetFromBlock(b types.Block, h types.BlockHeight) ConsensusBlocksGet {
    91  	txns := make([]ConsensusBlocksGetTxn, 0, len(b.Transactions))
    92  	for _, t := range b.Transactions {
    93  		// Get the transaction's SiacoinOutputs.
    94  		scos := make([]ConsensusBlocksGetSiacoinOutput, 0, len(t.SiacoinOutputs))
    95  		for i, sco := range t.SiacoinOutputs {
    96  			scos = append(scos, ConsensusBlocksGetSiacoinOutput{
    97  				ID:         t.SiacoinOutputID(uint64(i)),
    98  				Value:      sco.Value,
    99  				UnlockHash: sco.UnlockHash,
   100  			})
   101  		}
   102  		// Get the transaction's SiafundOutputs.
   103  		sfos := make([]ConsensusBlocksGetSiafundOutput, 0, len(t.SiafundOutputs))
   104  		for i, sfo := range t.SiafundOutputs {
   105  			sfos = append(sfos, ConsensusBlocksGetSiafundOutput{
   106  				ID:         t.SiafundOutputID(uint64(i)),
   107  				Value:      sfo.Value,
   108  				UnlockHash: sfo.UnlockHash,
   109  			})
   110  		}
   111  		// Get the transaction's FileContracts.
   112  		fcos := make([]ConsensusBlocksGetFileContract, 0, len(t.FileContracts))
   113  		for i, fc := range t.FileContracts {
   114  			// Get the FileContract's valid proof outputs.
   115  			fcid := t.FileContractID(uint64(i))
   116  			vpos := make([]ConsensusBlocksGetSiacoinOutput, 0, len(fc.ValidProofOutputs))
   117  			for j, vpo := range fc.ValidProofOutputs {
   118  				vpos = append(vpos, ConsensusBlocksGetSiacoinOutput{
   119  					ID:         fcid.StorageProofOutputID(types.ProofValid, uint64(j)),
   120  					Value:      vpo.Value,
   121  					UnlockHash: vpo.UnlockHash,
   122  				})
   123  			}
   124  			// Get the FileContract's missed proof outputs.
   125  			mpos := make([]ConsensusBlocksGetSiacoinOutput, 0, len(fc.MissedProofOutputs))
   126  			for j, mpo := range fc.MissedProofOutputs {
   127  				mpos = append(mpos, ConsensusBlocksGetSiacoinOutput{
   128  					ID:         fcid.StorageProofOutputID(types.ProofMissed, uint64(j)),
   129  					Value:      mpo.Value,
   130  					UnlockHash: mpo.UnlockHash,
   131  				})
   132  			}
   133  			fcos = append(fcos, ConsensusBlocksGetFileContract{
   134  				ID:                 fcid,
   135  				FileSize:           fc.FileSize,
   136  				FileMerkleRoot:     fc.FileMerkleRoot,
   137  				WindowStart:        fc.WindowStart,
   138  				WindowEnd:          fc.WindowEnd,
   139  				Payout:             fc.Payout,
   140  				ValidProofOutputs:  vpos,
   141  				MissedProofOutputs: mpos,
   142  				UnlockHash:         fc.UnlockHash,
   143  				RevisionNumber:     fc.RevisionNumber,
   144  			})
   145  		}
   146  		txns = append(txns, ConsensusBlocksGetTxn{
   147  			ID:                    t.ID(),
   148  			SiacoinInputs:         t.SiacoinInputs,
   149  			SiacoinOutputs:        scos,
   150  			FileContracts:         fcos,
   151  			FileContractRevisions: t.FileContractRevisions,
   152  			StorageProofs:         t.StorageProofs,
   153  			SiafundInputs:         t.SiafundInputs,
   154  			SiafundOutputs:        sfos,
   155  			MinerFees:             t.MinerFees,
   156  			ArbitraryData:         t.ArbitraryData,
   157  			TransactionSignatures: t.TransactionSignatures,
   158  		})
   159  	}
   160  	return ConsensusBlocksGet{
   161  		ID:           b.ID(),
   162  		Height:       h,
   163  		ParentID:     b.ParentID,
   164  		Nonce:        b.Nonce,
   165  		Timestamp:    b.Timestamp,
   166  		MinerPayouts: b.MinerPayouts,
   167  		Transactions: txns,
   168  	}
   169  }
   170  
   171  // consensusHandler handles the API calls to /consensus.
   172  func (api *API) consensusHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
   173  	cbid := api.cs.CurrentBlock().ID()
   174  	currentTarget, _ := api.cs.ChildTarget(cbid)
   175  	WriteJSON(w, ConsensusGET{
   176  		Synced:       api.cs.Synced(),
   177  		Height:       api.cs.Height(),
   178  		CurrentBlock: cbid,
   179  		Target:       currentTarget,
   180  		Difficulty:   currentTarget.Difficulty(),
   181  	})
   182  }
   183  
   184  // consensusBlocksIDHandler handles the API calls to /consensus/blocks
   185  // endpoint.
   186  func (api *API) consensusBlocksHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
   187  	// Get query params and check them.
   188  	id, height := req.FormValue("id"), req.FormValue("height")
   189  	if id != "" && height != "" {
   190  		WriteError(w, Error{"can't specify both id and height"}, http.StatusBadRequest)
   191  	}
   192  	if id == "" && height == "" {
   193  		WriteError(w, Error{"either id or height has to be provided"}, http.StatusBadRequest)
   194  	}
   195  
   196  	var b types.Block
   197  	var h types.BlockHeight
   198  	var exists bool
   199  
   200  	// Handle request by id
   201  	if id != "" {
   202  		var bid types.BlockID
   203  		if err := bid.LoadString(id); err != nil {
   204  			WriteError(w, Error{"failed to unmarshal blockid"}, http.StatusBadRequest)
   205  			return
   206  		}
   207  		b, h, exists = api.cs.BlockByID(bid)
   208  	}
   209  	// Handle request by height
   210  	if height != "" {
   211  		if _, err := fmt.Sscan(height, &h); err != nil {
   212  			WriteError(w, Error{"failed to parse block height"}, http.StatusBadRequest)
   213  			return
   214  		}
   215  		b, exists = api.cs.BlockAtHeight(types.BlockHeight(h))
   216  	}
   217  	// Check if block was found
   218  	if !exists {
   219  		WriteError(w, Error{"block doesn't exist"}, http.StatusBadRequest)
   220  		return
   221  	}
   222  	// Write response
   223  	WriteJSON(w, consensusBlocksGetFromBlock(b, h))
   224  }
   225  
   226  // consensusValidateTransactionsetHandler handles the API calls to
   227  // /consensus/validate/transactionset.
   228  func (api *API) consensusValidateTransactionsetHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
   229  	var txnset []types.Transaction
   230  	err := json.NewDecoder(req.Body).Decode(&txnset)
   231  	if err != nil {
   232  		WriteError(w, Error{"could not decode transaction set: " + err.Error()}, http.StatusBadRequest)
   233  		return
   234  	}
   235  	_, err = api.cs.TryTransactionSet(txnset)
   236  	if err != nil {
   237  		WriteError(w, Error{"transaction set validation failed: " + err.Error()}, http.StatusBadRequest)
   238  		return
   239  	}
   240  	WriteSuccess(w)
   241  }