本文整理匯總了Golang中github.com/NebulousLabs/Sia/types.Transaction.FileContractID方法的典型用法代碼示例。如果您正苦於以下問題:Golang Transaction.FileContractID方法的具體用法?Golang Transaction.FileContractID怎麽用?Golang Transaction.FileContractID使用的例子?那麽, 這裏精選的方法代碼示例或許可以為您提供幫助。您也可以進一步了解該方法所在類github.com/NebulousLabs/Sia/types.Transaction
的用法示例。
在下文中一共展示了Transaction.FileContractID方法的12個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: applyFileContracts
// applyFileContracts iterates through all of the file contracts in a
// transaction and applies them to the state, updating the diffs in the block
// node.
func (cs *State) applyFileContracts(bn *blockNode, t types.Transaction) {
for i, fc := range t.FileContracts {
// Sanity check - the file contract should not exists within the state.
fcid := t.FileContractID(i)
if build.DEBUG {
_, exists := cs.fileContracts[fcid]
if exists {
panic(ErrMisuseApplyFileContracts)
}
}
fcd := modules.FileContractDiff{
Direction: modules.DiffApply,
ID: fcid,
FileContract: fc,
}
bn.fileContractDiffs = append(bn.fileContractDiffs, fcd)
cs.commitFileContractDiff(fcd, modules.DiffApply)
// Get the portion of the contract that goes into the siafund pool and
// add it to the siafund pool.
sfpd := modules.SiafundPoolDiff{
Previous: cs.siafundPool,
Adjusted: cs.siafundPool.Add(fc.Tax()),
}
bn.siafundPoolDiffs = append(bn.siafundPoolDiffs, sfpd)
cs.commitSiafundPoolDiff(sfpd, modules.DiffApply)
}
return
}
示例2: removeFileContracts
// removeFileContracts removes all of the file contracts of a transaction from
// the unconfirmed consensus set.
func (tp *TransactionPool) removeFileContracts(t types.Transaction) {
for i, _ := range t.FileContracts {
fcid := t.FileContractID(i)
// Sanity check - file contract should be in the unconfirmed set as
// there should be no dependent transactions who have terminated the
// contract.
if build.DEBUG {
_, exists := tp.fileContracts[fcid]
if !exists {
panic("trying to remove missing file contract")
}
}
delete(tp.fileContracts, fcid)
}
}
示例3: TestDuplicateStorageProof
// TestDuplicateStorageProof applies a storage proof which has already been
// applied.
func TestDuplicateStorageProof(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
cst, err := createConsensusSetTester("TestDuplicateStorageProof")
if err != nil {
t.Fatal(err)
}
// Create a block node.
bn := new(blockNode)
bn.height = cst.cs.height()
// Create a file contract for the storage proof to prove.
txn0 := types.Transaction{
FileContracts: []types.FileContract{
{
Payout: types.NewCurrency64(300e3),
ValidProofOutputs: []types.SiacoinOutput{
{Value: types.NewCurrency64(290e3)},
},
},
},
}
cst.cs.applyFileContracts(bn, txn0)
fcid := txn0.FileContractID(0)
// Apply a single storage proof.
txn1 := types.Transaction{
StorageProofs: []types.StorageProof{{ParentID: fcid}},
}
cst.cs.applyStorageProofs(bn, txn1)
// Trigger a panic by applying the storage proof again.
defer func() {
r := recover()
if r != ErrDuplicateValidProofOutput {
t.Error("failed to trigger ErrDuplicateValidProofOutput:", r)
}
}()
cst.cs.applyFileContracts(bn, txn0) // File contract was consumed by the first proof.
cst.cs.applyStorageProofs(bn, txn1)
}
示例4: applyFileContracts
// applyFileContracts iterates through all of the file contracts in a
// transaction and applies them to the state, updating the diffs in the proccesed
// block.
func applyFileContracts(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
for i, fc := range t.FileContracts {
fcid := t.FileContractID(uint64(i))
fcd := modules.FileContractDiff{
Direction: modules.DiffApply,
ID: fcid,
FileContract: fc,
}
pb.FileContractDiffs = append(pb.FileContractDiffs, fcd)
commitFileContractDiff(tx, fcd, modules.DiffApply)
// Get the portion of the contract that goes into the siafund pool and
// add it to the siafund pool.
sfp := getSiafundPool(tx)
sfpd := modules.SiafundPoolDiff{
Direction: modules.DiffApply,
Previous: sfp,
Adjusted: sfp.Add(types.Tax(blockHeight(tx), fc.Payout)),
}
pb.SiafundPoolDiffs = append(pb.SiafundPoolDiffs, sfpd)
commitSiafundPoolDiff(tx, sfpd, modules.DiffApply)
}
}
示例5: applyFileContracts
// applyFileContracts iterates through all of the file contracts in a
// transaction and applies them to the state, updating the diffs in the proccesed
// block.
func (cs *ConsensusSet) applyFileContracts(tx *bolt.Tx, pb *processedBlock, t types.Transaction) error {
for i, fc := range t.FileContracts {
fcid := t.FileContractID(i)
fcd := modules.FileContractDiff{
Direction: modules.DiffApply,
ID: fcid,
FileContract: fc,
}
pb.FileContractDiffs = append(pb.FileContractDiffs, fcd)
cs.commitTxFileContractDiff(tx, fcd, modules.DiffApply)
// Get the portion of the contract that goes into the siafund pool and
// add it to the siafund pool.
sfp := getSiafundPool(tx)
sfpd := modules.SiafundPoolDiff{
Direction: modules.DiffApply,
Previous: sfp,
Adjusted: sfp.Add(fc.Tax()),
}
pb.SiafundPoolDiffs = append(pb.SiafundPoolDiffs, sfpd)
cs.commitTxSiafundPoolDiff(tx, sfpd, modules.DiffApply)
}
return nil
}
示例6: buildExplorerTransaction
// buildExplorerTransaction takes a transaction and the height + id of the
// block it appears in an uses that to build an explorer transaction.
func (srv *Server) buildExplorerTransaction(height types.BlockHeight, parent types.BlockID, txn types.Transaction) (et ExplorerTransaction) {
// Get the header information for the transaction.
et.ID = txn.ID()
et.Height = height
et.Parent = parent
et.RawTransaction = txn
// Add the siacoin outputs that correspond with each siacoin input.
for _, sci := range txn.SiacoinInputs {
sco, exists := srv.explorer.SiacoinOutput(sci.ParentID)
if build.DEBUG && !exists {
panic("could not find corresponding siacoin output")
}
et.SiacoinInputOutputs = append(et.SiacoinInputOutputs, sco)
}
for i := range txn.SiacoinOutputs {
et.SiacoinOutputIDs = append(et.SiacoinOutputIDs, txn.SiacoinOutputID(uint64(i)))
}
// Add all of the valid and missed proof ids as extra data to the file
// contracts.
for i, fc := range txn.FileContracts {
fcid := txn.FileContractID(uint64(i))
var fcvpoids []types.SiacoinOutputID
var fcmpoids []types.SiacoinOutputID
for j := range fc.ValidProofOutputs {
fcvpoids = append(fcvpoids, fcid.StorageProofOutputID(types.ProofValid, uint64(j)))
}
for j := range fc.MissedProofOutputs {
fcmpoids = append(fcmpoids, fcid.StorageProofOutputID(types.ProofMissed, uint64(j)))
}
et.FileContractIDs = append(et.FileContractIDs, fcid)
et.FileContractValidProofOutputIDs = append(et.FileContractValidProofOutputIDs, fcvpoids)
et.FileContractMissedProofOutputIDs = append(et.FileContractMissedProofOutputIDs, fcmpoids)
}
// Add all of the valid and missed proof ids as extra data to the file
// contract revisions.
for _, fcr := range txn.FileContractRevisions {
var fcrvpoids []types.SiacoinOutputID
var fcrmpoids []types.SiacoinOutputID
for j := range fcr.NewValidProofOutputs {
fcrvpoids = append(fcrvpoids, fcr.ParentID.StorageProofOutputID(types.ProofValid, uint64(j)))
}
for j := range fcr.NewMissedProofOutputs {
fcrmpoids = append(fcrmpoids, fcr.ParentID.StorageProofOutputID(types.ProofMissed, uint64(j)))
}
et.FileContractValidProofOutputIDs = append(et.FileContractValidProofOutputIDs, fcrvpoids)
et.FileContractMissedProofOutputIDs = append(et.FileContractMissedProofOutputIDs, fcrmpoids)
}
// Add all of the output ids and outputs corresponding with each storage
// proof.
for _, sp := range txn.StorageProofs {
fileContract, fileContractRevisions, fileContractExists, _ := srv.explorer.FileContractHistory(sp.ParentID)
if !fileContractExists && build.DEBUG {
panic("could not find a file contract connected with a storage proof")
}
var storageProofOutputs []types.SiacoinOutput
if len(fileContractRevisions) > 0 {
storageProofOutputs = fileContractRevisions[len(fileContractRevisions)-1].NewValidProofOutputs
} else {
storageProofOutputs = fileContract.ValidProofOutputs
}
var storageProofOutputIDs []types.SiacoinOutputID
for i := range storageProofOutputs {
storageProofOutputIDs = append(storageProofOutputIDs, sp.ParentID.StorageProofOutputID(types.ProofValid, uint64(i)))
}
et.StorageProofOutputIDs = append(et.StorageProofOutputIDs, storageProofOutputIDs)
et.StorageProofOutputs = append(et.StorageProofOutputs, storageProofOutputs)
}
// Add the siafund outputs that correspond to each siacoin input.
for _, sci := range txn.SiafundInputs {
sco, exists := srv.explorer.SiafundOutput(sci.ParentID)
if build.DEBUG && !exists {
panic("could not find corresponding siafund output")
}
et.SiafundInputOutputs = append(et.SiafundInputOutputs, sco)
}
for i := range txn.SiafundOutputs {
et.SiafundOutputIDs = append(et.SiafundOutputIDs, txn.SiafundOutputID(uint64(i)))
}
for _, sfi := range txn.SiafundInputs {
et.SiaClaimOutputIDs = append(et.SiaClaimOutputIDs, sfi.ParentID.SiaClaimOutputID())
}
return et
}
示例7: addTransaction
// addTransaction is called from addBlockDB, and delegates the adding
// of information to the database to the functions defined above
func (tx *boltTx) addTransaction(txn types.Transaction) {
// Store this for quick lookup
txid := txn.ID()
// Append each input to the list of modifications
for _, input := range txn.SiacoinInputs {
tx.addAddress(input.UnlockConditions.UnlockHash(), txid)
tx.addSiacoinInput(input.ParentID, txid)
}
// Handle all the transaction outputs
for i, output := range txn.SiacoinOutputs {
tx.addAddress(output.UnlockHash, txid)
tx.addNewOutput(txn.SiacoinOutputID(uint64(i)), txid)
}
// Handle each file contract individually
for i, contract := range txn.FileContracts {
fcid := txn.FileContractID(uint64(i))
tx.addNewHash("FileContracts", hashFilecontract, crypto.Hash(fcid), fcInfo{
Contract: txid,
})
for j, output := range contract.ValidProofOutputs {
tx.addAddress(output.UnlockHash, txid)
tx.addNewOutput(fcid.StorageProofOutputID(true, uint64(j)), txid)
}
for j, output := range contract.MissedProofOutputs {
tx.addAddress(output.UnlockHash, txid)
tx.addNewOutput(fcid.StorageProofOutputID(false, uint64(j)), txid)
}
tx.addAddress(contract.UnlockHash, txid)
}
// Update the list of revisions
for _, revision := range txn.FileContractRevisions {
tx.addFcRevision(revision.ParentID, txid)
// Note the old outputs will still be there in the
// database. This is to provide information to the
// people who may just need it.
for i, output := range revision.NewValidProofOutputs {
tx.addAddress(output.UnlockHash, txid)
tx.addNewOutput(revision.ParentID.StorageProofOutputID(true, uint64(i)), txid)
}
for i, output := range revision.NewMissedProofOutputs {
tx.addAddress(output.UnlockHash, txid)
tx.addNewOutput(revision.ParentID.StorageProofOutputID(false, uint64(i)), txid)
}
tx.addAddress(revision.NewUnlockHash, txid)
}
// Update the list of storage proofs
for _, proof := range txn.StorageProofs {
tx.addFcProof(proof.ParentID, txid)
}
// Append all the siafund inputs to the modification list
for _, input := range txn.SiafundInputs {
tx.addSiafundInput(input.ParentID, txid)
}
// Handle all the siafund outputs
for i, output := range txn.SiafundOutputs {
tx.addAddress(output.UnlockHash, txid)
tx.addNewSFOutput(txn.SiafundOutputID(uint64(i)), txid)
}
tx.putObject("Hashes", txid, hashTransaction)
}
示例8: TestApplyStorageProofs
// TestApplyStorageProofs probes the applyStorageProofs method of the consensus
// set.
func TestApplyStorageProofs(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
cst, err := createConsensusSetTester("TestApplyStorageProofs")
if err != nil {
t.Fatal(err)
}
// Create a block node to use with application.
bn := new(blockNode)
bn.height = cst.cs.height()
// Apply a transaction with two file contracts - there is a reason to
// create a storage proof.
txn := types.Transaction{
FileContracts: []types.FileContract{
{
Payout: types.NewCurrency64(300e3),
ValidProofOutputs: []types.SiacoinOutput{
{Value: types.NewCurrency64(290e3)},
},
},
{},
{
Payout: types.NewCurrency64(600e3),
ValidProofOutputs: []types.SiacoinOutput{
{Value: types.NewCurrency64(280e3)},
{Value: types.NewCurrency64(300e3)},
},
},
},
}
cst.cs.applyFileContracts(bn, txn)
fcid0 := txn.FileContractID(0)
fcid1 := txn.FileContractID(1)
fcid2 := txn.FileContractID(2)
// Apply a single storage proof.
txn = types.Transaction{
StorageProofs: []types.StorageProof{{ParentID: fcid0}},
}
cst.cs.applyStorageProofs(bn, txn)
_, exists := cst.cs.fileContracts[fcid0]
if exists {
t.Error("Storage proof did not disable a file contract.")
}
if len(cst.cs.fileContracts) != 2 {
t.Error("file contracts not correctly updated")
}
if len(bn.fileContractDiffs) != 4 { // 3 creating the initial contracts, 1 for the storage proof.
t.Error("block node was not updated for single element transaction")
}
if bn.fileContractDiffs[3].Direction != modules.DiffRevert {
t.Error("wrong diff direction applied when revising a file contract")
}
if bn.fileContractDiffs[3].ID != fcid0 {
t.Error("wrong id used when revising a file contract")
}
spoid0 := fcid0.StorageProofOutputID(types.ProofValid, 0)
sco, exists := cst.cs.delayedSiacoinOutputs[bn.height+types.MaturityDelay][spoid0]
if !exists {
t.Error("storage proof output not created after applying a storage proof")
}
if sco.Value.Cmp(types.NewCurrency64(290e3)) != 0 {
t.Error("storage proof output was created with the wrong value")
}
// Apply a transaction with 2 storage proofs.
txn = types.Transaction{
StorageProofs: []types.StorageProof{
{ParentID: fcid1},
{ParentID: fcid2},
},
}
cst.cs.applyStorageProofs(bn, txn)
_, exists = cst.cs.fileContracts[fcid1]
if exists {
t.Error("Storage proof failed to consume file contract.")
}
_, exists = cst.cs.fileContracts[fcid2]
if exists {
t.Error("storage proof did not consume file contract")
}
if len(cst.cs.fileContracts) != 0 {
t.Error("file contracts not correctly updated")
}
if len(bn.fileContractDiffs) != 6 {
t.Error("block node was not updated correctly")
}
spoid1 := fcid1.StorageProofOutputID(types.ProofValid, 0)
_, exists = cst.cs.siacoinOutputs[spoid1]
if exists {
t.Error("output created when file contract had no corresponding output")
}
spoid2 := fcid2.StorageProofOutputID(types.ProofValid, 0)
sco, exists = cst.cs.delayedSiacoinOutputs[bn.height+types.MaturityDelay][spoid2]
if !exists {
//.........這裏部分代碼省略.........
示例9: TestApplyFileContractRevisions
// TestApplyFileContractRevisions probes the applyFileContractRevisions method
// of the consensus set.
func TestApplyFileContractRevisions(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
cst, err := createConsensusSetTester("TestApplyFileContractRevisions")
if err != nil {
t.Fatal(err)
}
// Create a block node to use with application.
bn := new(blockNode)
// Apply a transaction with two file contracts - that way there is
// something to revise.
txn := types.Transaction{
FileContracts: []types.FileContract{
{},
{Payout: types.NewCurrency64(1)},
},
}
cst.cs.applyFileContracts(bn, txn)
fcid0 := txn.FileContractID(0)
fcid1 := txn.FileContractID(1)
// Apply a single file contract revision.
txn = types.Transaction{
FileContractRevisions: []types.FileContractRevision{
{
ParentID: fcid0,
NewFileSize: 1,
},
},
}
cst.cs.applyFileContractRevisions(bn, txn)
fc, exists := cst.cs.fileContracts[fcid0]
if !exists {
t.Error("Revision killed a file contract")
}
if fc.FileSize != 1 {
t.Error("file contract filesize not properly updated")
}
if len(cst.cs.fileContracts) != 2 {
t.Error("file contracts not correctly updated")
}
if len(bn.fileContractDiffs) != 4 { // 2 creating the initial contracts, 1 to remove the old, 1 to add the revision.
t.Error("block node was not updated for single element transaction")
}
if bn.fileContractDiffs[2].Direction != modules.DiffRevert {
t.Error("wrong diff direction applied when revising a file contract")
}
if bn.fileContractDiffs[3].Direction != modules.DiffApply {
t.Error("wrong diff direction applied when revising a file contract")
}
if bn.fileContractDiffs[2].ID != fcid0 {
t.Error("wrong id used when revising a file contract")
}
if bn.fileContractDiffs[3].ID != fcid0 {
t.Error("wrong id used when revising a file contract")
}
// Apply a transaction with 2 file contract revisions.
txn = types.Transaction{
FileContractRevisions: []types.FileContractRevision{
{
ParentID: fcid0,
NewFileSize: 2,
},
{
ParentID: fcid1,
NewFileSize: 3,
},
},
}
cst.cs.applyFileContractRevisions(bn, txn)
fc0, exists := cst.cs.fileContracts[fcid0]
if !exists {
t.Error("Revision ate file contract")
}
fc1, exists := cst.cs.fileContracts[fcid1]
if !exists {
t.Error("Revision ate file contract")
}
if fc0.FileSize != 2 {
t.Error("Revision not correctly applied")
}
if fc1.FileSize != 3 {
t.Error("Revision not correctly applied")
}
if len(cst.cs.fileContracts) != 2 {
t.Error("file contracts not correctly updated")
}
if len(bn.fileContractDiffs) != 8 {
t.Error("block node was not updated correctly")
}
}
示例10: TestApplyFileContracts
// TestApplyFileContracts probes the applyFileContracts method of the
// consensus set.
func TestApplyFileContracts(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
cst, err := createConsensusSetTester("TestApplyFileContracts")
if err != nil {
t.Fatal(err)
}
// Create a block node to use with application.
bn := new(blockNode)
// Apply a transaction with a single file contract.
txn := types.Transaction{
FileContracts: []types.FileContract{{}},
}
cst.cs.applyFileContracts(bn, txn)
fcid := txn.FileContractID(0)
_, exists := cst.cs.fileContracts[fcid]
if !exists {
t.Error("Failed to create file contract")
}
if len(cst.cs.fileContracts) != 1 {
t.Error("file contracts not correctly updated")
}
if len(bn.fileContractDiffs) != 1 {
t.Error("block node was not updated for single element transaction")
}
if bn.fileContractDiffs[0].Direction != modules.DiffApply {
t.Error("wrong diff direction applied when creating a file contract")
}
if bn.fileContractDiffs[0].ID != fcid {
t.Error("wrong id used when creating a file contract")
}
// Apply a transaction with 2 file contracts.
txn = types.Transaction{
FileContracts: []types.FileContract{
{Payout: types.NewCurrency64(1)},
{Payout: types.NewCurrency64(300e3)},
},
}
cst.cs.applyFileContracts(bn, txn)
fcid0 := txn.FileContractID(0)
fcid1 := txn.FileContractID(1)
_, exists = cst.cs.fileContracts[fcid0]
if !exists {
t.Error("Failed to create file contract")
}
_, exists = cst.cs.fileContracts[fcid1]
if !exists {
t.Error("Failed to create file contract")
}
if len(cst.cs.fileContracts) != 3 {
t.Error("file contracts not correctly updated")
}
if len(bn.fileContractDiffs) != 3 {
t.Error("block node was not updated correctly")
}
if cst.cs.siafundPool.Cmp(types.NewCurrency64(10e3)) != 0 {
t.Error("siafund pool did not update correctly upon creation of a file contract")
}
}
示例11: TestUploadConstraints
//.........這裏部分代碼省略.........
underPayment := types.NewCurrency64(filesize * 5 / 6).Mul(settings.Price).Mul(currencyDuration)
underRefund := types.PostTax(ht.cs.Height(), payout).Sub(underPayment)
txn.FileContracts[0].ValidProofOutputs[0].Value = underRefund
txn.FileContracts[0].ValidProofOutputs[1].Value = underPayment
txn.FileContracts[0].MissedProofOutputs[0].Value = underRefund
txn.FileContracts[0].MissedProofOutputs[1].Value = underPayment
err = h.considerContract(txn, renterKey, filesize, merkleRoot)
if err != ErrLowPayment {
t.Fatal(err)
}
// Test that too-large files get rejected.
largeFilesize := uint64(10001)
largeFilePayment := types.NewCurrency64(largeFilesize).Mul(settings.Price).Mul(currencyDuration)
largeFileRefund := types.PostTax(ht.cs.Height(), payout).Sub(largeFilePayment)
txn.FileContracts[0].FileSize = largeFilesize
txn.FileContracts[0].ValidProofOutputs[0].Value = largeFileRefund
txn.FileContracts[0].ValidProofOutputs[1].Value = largeFilePayment
txn.FileContracts[0].MissedProofOutputs[0].Value = largeFileRefund
txn.FileContracts[0].MissedProofOutputs[1].Value = largeFilePayment
err = h.considerContract(txn, renterKey, largeFilesize, merkleRoot)
if err != ErrHostCapacity {
t.Fatal(err)
}
// Reset the file contract to a working contract, and create an obligation
// from the transaction.
txn.FileContracts[0].FileSize = filesize
txn.FileContracts[0].ValidProofOutputs[0].Value = refund
txn.FileContracts[0].ValidProofOutputs[1].Value = payment
txn.FileContracts[0].MissedProofOutputs[0].Value = refund
txn.FileContracts[0].MissedProofOutputs[1].Value = payment
obligation := &contractObligation{
ID: txn.FileContractID(0),
OriginTransaction: txn,
}
// Create a legal revision transaction.
newFileSize := filesize + uint64(4e3)
revisedPayment := payment.Add(types.NewCurrency64(newFileSize - filesize).Mul(currencyDuration).Mul(settings.Price))
revisedRefund := types.PostTax(ht.cs.Height(), payout).Sub(revisedPayment)
revisionTxn := types.Transaction{
FileContractRevisions: []types.FileContractRevision{{
ParentID: txn.FileContractID(0),
UnlockConditions: types.UnlockConditions{
PublicKeys: []types.SiaPublicKey{renterKey, h.publicKey},
SignaturesRequired: 2,
},
NewRevisionNumber: txn.FileContracts[0].RevisionNumber + 1,
NewFileSize: newFileSize,
NewFileMerkleRoot: merkleRoot,
NewWindowStart: windowStart,
NewWindowEnd: windowEnd,
NewValidProofOutputs: []types.SiacoinOutput{
{
Value: revisedRefund,
UnlockHash: types.UnlockHash{},
},
{
Value: revisedPayment,
UnlockHash: settings.UnlockHash,
},
},
NewMissedProofOutputs: []types.SiacoinOutput{
{
示例12: rpcContract
//.........這裏部分代碼省略.........
// signal that we are ready to download file
err = encoding.WriteObject(conn, modules.AcceptTermsResponse)
if err != nil {
return
}
// simultaneously download file and calculate its Merkle root.
tee := io.TeeReader(
// use a LimitedReader to ensure we don't read indefinitely
io.LimitReader(conn, int64(terms.FileSize)),
// each byte we read from tee will also be written to file
file,
)
merkleRoot, err := crypto.ReaderMerkleRoot(tee)
if err != nil {
return
}
// Data has been sent, read in the unsigned transaction with the file
// contract.
var unsignedTxn types.Transaction
err = encoding.ReadObject(conn, &unsignedTxn, maxContractLen)
if err != nil {
return
}
// Verify that the transaction matches the agreed upon terms, and that the
// Merkle root in the file contract matches our independently calculated
// Merkle root.
err = verifyTransaction(unsignedTxn, terms, merkleRoot)
if err != nil {
err = errors.New("transaction does not satisfy terms: " + err.Error())
return
}
// Add the collateral to the transaction, but do not sign the transaction.
collateralTxn, txnBuilder, err := h.addCollateral(unsignedTxn, terms)
if err != nil {
return
}
err = encoding.WriteObject(conn, collateralTxn)
if err != nil {
return
}
// Read in the renter-signed transaction and check that it matches the
// previously accepted transaction.
var signedTxn types.Transaction
err = encoding.ReadObject(conn, &signedTxn, maxContractLen)
if err != nil {
return
}
if collateralTxn.ID() != signedTxn.ID() {
err = errors.New("signed transaction does not match the transaction with collateral")
return
}
// Add the signatures from the renter signed transaction, and then sign the
// transaction, then submit the transaction.
for _, sig := range signedTxn.TransactionSignatures {
txnBuilder.AddTransactionSignature(sig)
if err != nil {
return
}
}
txnSet, err := txnBuilder.Sign(true)
if err != nil {
return
}
err = h.tpool.AcceptTransactionSet(txnSet)
if err != nil {
return
}
// Add this contract to the host's list of obligations.
fcid := signedTxn.FileContractID(0)
fc := signedTxn.FileContracts[0]
proofHeight := fc.WindowStart + StorageProofReorgDepth
co := contractObligation{
ID: fcid,
FileContract: fc,
Path: path,
}
lockID = h.mu.Lock()
h.obligationsByHeight[proofHeight] = append(h.obligationsByHeight[proofHeight], co)
h.obligationsByID[fcid] = co
h.save()
h.mu.Unlock(lockID)
// Send an ack to the renter that all is well.
err = encoding.WriteObject(conn, true)
if err != nil {
return
}
// TODO: we don't currently watch the blockchain to make sure that the
// transaction actually gets into the blockchain.
return
}