本文整理匯總了Golang中github.com/NebulousLabs/Sia/types.PostTax函數的典型用法代碼示例。如果您正苦於以下問題:Golang PostTax函數的具體用法?Golang PostTax怎麽用?Golang PostTax使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了PostTax函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: newTesterStorageObligation
// newTesterStorageObligation uses the wallet to create and fund a file
// contract that will form the foundation of a storage obligation.
func (ht *hostTester) newTesterStorageObligation() (*storageObligation, error) {
// Create the file contract that will be used in the obligation.
builder := ht.wallet.StartTransaction()
// Fund the file contract with a payout. The payout needs to be big enough
// that the expected revenue is larger than the fee that the host may end
// up paying.
payout := types.SiacoinPrecision.Mul64(1e3)
err := builder.FundSiacoins(payout)
if err != nil {
return nil, err
}
// Add the file contract that consumes the funds.
_ = builder.AddFileContract(types.FileContract{
// Because this file contract needs to be able to accept file contract
// revisions, the expiration is put more than
// 'revisionSubmissionBuffer' blocks into the future.
WindowStart: ht.host.blockHeight + revisionSubmissionBuffer + 2,
WindowEnd: ht.host.blockHeight + revisionSubmissionBuffer + defaultWindowSize + 2,
Payout: payout,
ValidProofOutputs: []types.SiacoinOutput{
{
Value: types.PostTax(ht.host.blockHeight, payout),
},
{
Value: types.ZeroCurrency,
},
},
MissedProofOutputs: []types.SiacoinOutput{
{
Value: types.PostTax(ht.host.blockHeight, payout),
},
{
Value: types.ZeroCurrency,
},
},
UnlockHash: (types.UnlockConditions{}).UnlockHash(),
RevisionNumber: 0,
})
// Sign the transaction.
tSet, err := builder.Sign(true)
if err != nil {
return nil, err
}
// Assemble and return the storage obligation.
so := &storageObligation{
OriginTransactionSet: tSet,
// TODO: There are no tracking values, because no fees were added.
}
return so, nil
}
示例2: TestAcceptFCAndConflictingRevision
// TestAcceptFCAndConflictingRevision checks that the transaction pool
// correctly accepts a file contract in a transaction set followed by a correct
// revision to that file contract in the a following transaction set, with no
// block separating them.
func TestAcceptFCAndConflictingRevision(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
tpt, err := createTpoolTester("TestAcceptFCAndConflictingRevision")
if err != nil {
t.Fatal(err)
}
defer tpt.Close()
// Create and fund a valid file contract.
builder := tpt.wallet.StartTransaction()
payout := types.NewCurrency64(1e9)
err = builder.FundSiacoins(payout)
if err != nil {
t.Fatal(err)
}
builder.AddFileContract(types.FileContract{
WindowStart: tpt.cs.Height() + 2,
WindowEnd: tpt.cs.Height() + 5,
Payout: payout,
ValidProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(tpt.cs.Height(), payout)}},
MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(tpt.cs.Height(), payout)}},
UnlockHash: types.UnlockConditions{}.UnlockHash(),
})
tSet, err := builder.Sign(true)
if err != nil {
t.Fatal(err)
}
err = tpt.tpool.AcceptTransactionSet(tSet)
if err != nil {
t.Fatal(err)
}
fcid := tSet[len(tSet)-1].FileContractID(0)
// Create a file contract revision and submit it.
rSet := []types.Transaction{{
FileContractRevisions: []types.FileContractRevision{{
ParentID: fcid,
NewRevisionNumber: 2,
NewWindowStart: tpt.cs.Height() + 2,
NewWindowEnd: tpt.cs.Height() + 5,
NewValidProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(tpt.cs.Height(), payout)}},
NewMissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(tpt.cs.Height(), payout)}},
}},
}}
err = tpt.tpool.AcceptTransactionSet(rSet)
if err != nil {
t.Fatal(err)
}
}
示例3: TestNegotiateContract
func TestNegotiateContract(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
t.Parallel()
ct, err := newContractorTester("TestNegotiateContract")
if err != nil {
t.Fatal(err)
}
payout := types.NewCurrency64(1e16)
fc := types.FileContract{
FileSize: 0,
FileMerkleRoot: crypto.Hash{}, // no proof possible without data
WindowStart: 100,
WindowEnd: 1000,
Payout: payout,
ValidProofOutputs: []types.SiacoinOutput{
{Value: types.PostTax(ct.contractor.blockHeight, payout), UnlockHash: types.UnlockHash{}},
{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
},
MissedProofOutputs: []types.SiacoinOutput{
// same as above
{Value: types.PostTax(ct.contractor.blockHeight, payout), UnlockHash: types.UnlockHash{}},
// goes to the void, not the hostdb
{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
},
UnlockHash: types.UnlockHash{},
RevisionNumber: 0,
}
txnBuilder := ct.wallet.StartTransaction()
err = txnBuilder.FundSiacoins(fc.Payout)
if err != nil {
t.Fatal(err)
}
txnBuilder.AddFileContract(fc)
signedTxnSet, err := txnBuilder.Sign(true)
if err != nil {
t.Fatal(err)
}
err = ct.tpool.AcceptTransactionSet(signedTxnSet)
if err != nil {
t.Fatal(err)
}
}
示例4: considerRevision
// considerRevision checks that the provided file contract revision is still
// acceptable to the host.
func (h *Host) considerRevision(txn types.Transaction, obligation *contractObligation) error {
// Check that there is only one revision.
if len(txn.FileContractRevisions) != 1 {
return errors.New("transaction should have only one revision")
}
// calculate minimum expected output value
rev := txn.FileContractRevisions[0]
duration := types.NewCurrency64(uint64(obligation.windowStart() - h.blockHeight))
minHostPrice := types.NewCurrency64(rev.NewFileSize).Mul(duration).Mul(h.settings.Price)
expectedPayout := types.PostTax(h.blockHeight, obligation.payout())
switch {
// these fields should never change
case rev.ParentID != obligation.ID:
return errors.New("bad revision parent ID")
case rev.NewWindowStart != obligation.windowStart():
return errors.New("bad revision window start")
case rev.NewWindowEnd != obligation.windowEnd():
return errors.New("bad revision window end")
case rev.NewUnlockHash != obligation.unlockHash():
return errors.New("bad revision unlock hash")
case rev.UnlockConditions.UnlockHash() != obligation.unlockHash():
return errors.New("bad revision unlock conditions")
case len(rev.NewValidProofOutputs) != 2:
return errors.New("bad revision valid proof outputs")
case len(rev.NewMissedProofOutputs) != 2:
return errors.New("bad revision missed proof outputs")
case rev.NewValidProofOutputs[1].UnlockHash != obligation.validProofUnlockHash(),
rev.NewMissedProofOutputs[1].UnlockHash != obligation.missedProofUnlockHash():
return errors.New("bad revision proof outputs")
case rev.NewRevisionNumber <= obligation.revisionNumber():
return errors.New("revision must have higher revision number")
case rev.NewFileSize > uint64(h.spaceRemaining):
return errors.New("revision file size is too large")
case rev.NewFileSize <= obligation.fileSize():
return errors.New("revision must add data")
case rev.NewFileSize-obligation.fileSize() > maxRevisionSize:
return errors.New("revision adds too much data")
case rev.NewValidProofOutputs[0].Value.Add(rev.NewValidProofOutputs[1].Value).Cmp(expectedPayout) != 0,
// valid and missing outputs should still sum to payout
rev.NewMissedProofOutputs[0].Value.Add(rev.NewMissedProofOutputs[1].Value).Cmp(expectedPayout) != 0:
return errors.New("revision outputs do not sum to original payout")
case rev.NewValidProofOutputs[1].Value.Cmp(minHostPrice) < 0:
// outputs should have been adjusted proportional to the new filesize
return errors.New("revision price is too small")
case rev.NewMissedProofOutputs[0].Value.Cmp(rev.NewValidProofOutputs[0].Value) != 0:
return errors.New("revision missed renter payout does not match valid payout")
}
return nil
}
示例5: considerRevision
// considerRevision checks that the provided file contract revision is still
// acceptable to the host.
// TODO: should take a txn and check that is only contains the single revision
func (h *Host) considerRevision(txn types.Transaction, obligation contractObligation) error {
// Check that there is only one revision.
// TODO: check that the txn is empty except for the revision?
if len(txn.FileContractRevisions) != 1 {
return errors.New("transaction should have only one revision")
}
// calculate minimum expected output value
rev := txn.FileContractRevisions[0]
fc := obligation.FileContract
duration := types.NewCurrency64(uint64(fc.WindowStart - h.blockHeight))
minHostPrice := types.NewCurrency64(rev.NewFileSize).Mul(duration).Mul(h.Price)
expectedPayout := types.PostTax(h.blockHeight, fc.Payout)
switch {
// these fields should never change
case rev.ParentID != obligation.ID:
return errors.New("bad revision parent ID")
case rev.NewWindowStart != fc.WindowStart:
return errors.New("bad revision window start")
case rev.NewWindowEnd != fc.WindowEnd:
return errors.New("bad revision window end")
case rev.NewUnlockHash != fc.UnlockHash:
return errors.New("bad revision unlock hash")
case rev.UnlockConditions.UnlockHash() != fc.UnlockHash:
return errors.New("bad revision unlock conditions")
case len(rev.NewValidProofOutputs) != 2:
return errors.New("bad revision valid proof outputs")
case len(rev.NewMissedProofOutputs) != 2:
return errors.New("bad revision missed proof outputs")
case rev.NewValidProofOutputs[1].UnlockHash != fc.ValidProofOutputs[1].UnlockHash,
rev.NewMissedProofOutputs[1].UnlockHash != fc.MissedProofOutputs[1].UnlockHash:
return errors.New("bad revision proof outputs")
case rev.NewRevisionNumber <= fc.RevisionNumber:
return errors.New("revision must have higher revision number")
case rev.NewFileSize > uint64(h.spaceRemaining) || rev.NewFileSize > h.MaxFilesize:
return errors.New("revision file size is too large")
// valid and missing outputs should still sum to payout
case rev.NewValidProofOutputs[0].Value.Add(rev.NewValidProofOutputs[1].Value).Cmp(expectedPayout) != 0,
rev.NewMissedProofOutputs[0].Value.Add(rev.NewMissedProofOutputs[1].Value).Cmp(expectedPayout) != 0:
return errors.New("revision outputs do not sum to original payout")
// outputs should have been adjusted proportional to the new filesize
case rev.NewValidProofOutputs[1].Value.Cmp(minHostPrice) <= 0:
return errors.New("revision price is too small")
case rev.NewMissedProofOutputs[0].Value.Cmp(rev.NewValidProofOutputs[0].Value) != 0:
return errors.New("revision missed renter payout does not match valid payout")
}
return nil
}
示例6: Info
func (h *Host) Info() modules.HostInfo {
h.mu.RLock()
defer h.mu.RUnlock()
h.HostSettings.IPAddress = h.myAddr // needs to be updated manually
info := modules.HostInfo{
HostSettings: h.HostSettings,
StorageRemaining: h.spaceRemaining,
NumContracts: len(h.obligationsByID),
Profit: h.profit,
}
// sum up the current obligations to calculate PotentialProfit
for _, obligation := range h.obligationsByID {
fc := obligation.FileContract
info.PotentialProfit = info.PotentialProfit.Add(types.PostTax(h.blockHeight, fc.Payout))
}
return info
}
示例7: Info
func (h *Host) Info() modules.HostInfo {
lockID := h.mu.RLock()
defer h.mu.RUnlock(lockID)
info := modules.HostInfo{
HostSettings: h.HostSettings,
StorageRemaining: h.spaceRemaining,
NumContracts: len(h.obligationsByID),
Profit: h.profit,
}
// sum up the current obligations to calculate PotentialProfit
for _, obligation := range h.obligationsByID {
fc := obligation.FileContract
info.PotentialProfit = info.PotentialProfit.Add(types.PostTax(h.blockHeight, fc.Payout))
}
// Calculate estimated competition (reported in per GB per month). Price
// calculated by taking the average of hosts 8-15.
var averagePrice types.Currency
hosts := h.hostdb.RandomHosts(15)
for i, host := range hosts {
if i < 8 {
continue
}
averagePrice = averagePrice.Add(host.Price)
}
if len(hosts) == 0 {
return info
}
averagePrice = averagePrice.Div(types.NewCurrency64(uint64(len(hosts))))
// HACK: 4320 is one month, and 1024^3 is a GB. Price is reported as per GB
// per month.
estimatedCost := averagePrice.Mul(types.NewCurrency64(4320)).Mul(types.NewCurrency64(1024 * 1024 * 1024))
info.Competition = estimatedCost
return info
}
示例8: testValidStorageProofBlocks
// testValidStorageProofBlocks adds a block with a file contract, and then
// submits a storage proof for that file contract.
func (cst *consensusSetTester) testValidStorageProofBlocks() {
// COMPATv0.4.0 - Step the block height up past the hardfork amount. This
// code stops nondeterministic failures when producing storage proofs that
// is related to buggy old code.
for cst.cs.dbBlockHeight() <= 10 {
_, err := cst.miner.AddBlock()
if err != nil {
panic(err)
}
}
// Create a file (as a bytes.Buffer) that will be used for the file
// contract.
filesize := uint64(4e3)
file := randFile(filesize)
merkleRoot, err := crypto.ReaderMerkleRoot(file)
if err != nil {
panic(err)
}
file.Seek(0, 0)
// Create a file contract that will be successful.
validProofDest := randAddress()
payout := types.NewCurrency64(400e6)
fc := types.FileContract{
FileSize: filesize,
FileMerkleRoot: merkleRoot,
WindowStart: cst.cs.dbBlockHeight() + 1,
WindowEnd: cst.cs.dbBlockHeight() + 2,
Payout: payout,
ValidProofOutputs: []types.SiacoinOutput{{
UnlockHash: validProofDest,
Value: types.PostTax(cst.cs.dbBlockHeight(), payout),
}},
MissedProofOutputs: []types.SiacoinOutput{{
UnlockHash: types.UnlockHash{},
Value: types.PostTax(cst.cs.dbBlockHeight(), payout),
}},
}
// Submit a transaction with the file contract.
oldSiafundPool := cst.cs.dbGetSiafundPool()
txnBuilder := cst.wallet.StartTransaction()
err = txnBuilder.FundSiacoins(payout)
if err != nil {
panic(err)
}
fcIndex := txnBuilder.AddFileContract(fc)
txnSet, err := txnBuilder.Sign(true)
if err != nil {
panic(err)
}
err = cst.tpool.AcceptTransactionSet(txnSet)
if err != nil {
panic(err)
}
_, err = cst.miner.AddBlock()
if err != nil {
panic(err)
}
// Check that the siafund pool was increased by the tax on the payout.
siafundPool := cst.cs.dbGetSiafundPool()
if siafundPool.Cmp(oldSiafundPool.Add(types.Tax(cst.cs.dbBlockHeight()-1, payout))) != 0 {
panic("siafund pool was not increased correctly")
}
// Check that the file contract made it into the database.
ti := len(txnSet) - 1
fcid := txnSet[ti].FileContractID(fcIndex)
_, err = cst.cs.dbGetFileContract(fcid)
if err != nil {
panic(err)
}
// Create and submit a storage proof for the file contract.
segmentIndex, err := cst.cs.StorageProofSegment(fcid)
if err != nil {
panic(err)
}
segment, hashSet, err := crypto.BuildReaderProof(file, segmentIndex)
if err != nil {
panic(err)
}
sp := types.StorageProof{
ParentID: fcid,
HashSet: hashSet,
}
copy(sp.Segment[:], segment)
txnBuilder = cst.wallet.StartTransaction()
txnBuilder.AddStorageProof(sp)
txnSet, err = txnBuilder.Sign(true)
if err != nil {
panic(err)
}
err = cst.tpool.AcceptTransactionSet(txnSet)
if err != nil {
panic(err)
//.........這裏部分代碼省略.........
示例9: TestTaxHardfork
// COMPATv0.4.0
//
// This test checks that the hardfork scheduled for block 21,000 rolls through
// smoothly.
func TestTaxHardfork(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
cst, err := createConsensusSetTester("TestTaxHardfork")
if err != nil {
t.Fatal(err)
}
defer cst.closeCst()
// Create a file contract with a payout that is put into the blockchain
// before the hardfork block but expires after the hardfork block.
payout := types.NewCurrency64(400e6)
outputSize := types.PostTax(cst.cs.dbBlockHeight(), payout)
fc := types.FileContract{
WindowStart: cst.cs.dbBlockHeight() + 12,
WindowEnd: cst.cs.dbBlockHeight() + 14,
Payout: payout,
ValidProofOutputs: []types.SiacoinOutput{{Value: outputSize}},
MissedProofOutputs: []types.SiacoinOutput{{Value: outputSize}},
UnlockHash: types.UnlockConditions{}.UnlockHash(), // The empty UC is anyone-can-spend
}
// Create and fund a transaction with a file contract.
txnBuilder := cst.wallet.StartTransaction()
err = txnBuilder.FundSiacoins(payout)
if err != nil {
t.Fatal(err)
}
fcIndex := txnBuilder.AddFileContract(fc)
txnSet, err := txnBuilder.Sign(true)
if err != nil {
t.Fatal(err)
}
err = cst.tpool.AcceptTransactionSet(txnSet)
if err != nil {
t.Fatal(err)
}
_, err = cst.miner.AddBlock()
if err != nil {
t.Fatal(err)
}
// Check that the siafund pool was increased by the faulty float amount.
siafundPool := cst.cs.dbGetSiafundPool()
if siafundPool.Cmp(types.NewCurrency64(15590e3)) != 0 {
t.Fatal("siafund pool was not increased correctly")
}
// Mine blocks until the hardfork is reached.
for i := 0; i < 10; i++ {
_, err = cst.miner.AddBlock()
if err != nil {
t.Fatal(err)
}
}
// Submit a file contract revision and check that the payouts are able to
// be the same.
fcid := txnSet[len(txnSet)-1].FileContractID(fcIndex)
fcr := types.FileContractRevision{
ParentID: fcid,
UnlockConditions: types.UnlockConditions{},
NewRevisionNumber: 1,
NewFileSize: 1,
NewWindowStart: cst.cs.dbBlockHeight() + 2,
NewWindowEnd: cst.cs.dbBlockHeight() + 4,
NewValidProofOutputs: fc.ValidProofOutputs,
NewMissedProofOutputs: fc.MissedProofOutputs,
}
txnBuilder = cst.wallet.StartTransaction()
txnBuilder.AddFileContractRevision(fcr)
txnSet, err = txnBuilder.Sign(true)
if err != nil {
t.Fatal(err)
}
err = cst.tpool.AcceptTransactionSet(txnSet)
if err != nil {
t.Fatal(err)
}
_, err = cst.miner.AddBlock()
if err != nil {
t.Fatal(err)
}
// Mine blocks until the revision goes through, such that the sanity checks
// can be run.
for i := 0; i < 6; i++ {
_, err = cst.miner.AddBlock()
if err != nil {
t.Fatal(err)
}
}
// Check that the siafund pool did not change after the submitted revision.
//.........這裏部分代碼省略.........
示例10: TestReviseContract
func TestReviseContract(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
t.Parallel()
ct, err := newContractorTester("TestReviseContract")
if err != nil {
t.Fatal(err)
}
// get an address
ourAddr, err := ct.wallet.NextAddress()
if err != nil {
t.Fatal(err)
}
// generate keys
sk, pk, err := crypto.GenerateKeyPair()
if err != nil {
t.Fatal(err)
}
renterPubKey := types.SiaPublicKey{
Algorithm: types.SignatureEd25519,
Key: pk[:],
}
uc := types.UnlockConditions{
PublicKeys: []types.SiaPublicKey{renterPubKey, renterPubKey},
SignaturesRequired: 1,
}
// create file contract
payout := types.NewCurrency64(1e16)
fc := types.FileContract{
FileSize: 0,
FileMerkleRoot: crypto.Hash{}, // no proof possible without data
WindowStart: 100,
WindowEnd: 1000,
Payout: payout,
UnlockHash: uc.UnlockHash(),
RevisionNumber: 0,
}
// outputs need account for tax
fc.ValidProofOutputs = []types.SiacoinOutput{
{Value: types.PostTax(ct.contractor.blockHeight, payout), UnlockHash: ourAddr.UnlockHash()},
{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}}, // no collateral
}
fc.MissedProofOutputs = []types.SiacoinOutput{
// same as above
fc.ValidProofOutputs[0],
// goes to the void, not the hostdb
{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
}
txnBuilder := ct.wallet.StartTransaction()
err = txnBuilder.FundSiacoins(fc.Payout)
if err != nil {
t.Fatal(err)
}
txnBuilder.AddFileContract(fc)
signedTxnSet, err := txnBuilder.Sign(true)
if err != nil {
t.Fatal(err)
}
// submit contract
err = ct.tpool.AcceptTransactionSet(signedTxnSet)
if err != nil {
t.Fatal(err)
}
// create revision
fcid := signedTxnSet[len(signedTxnSet)-1].FileContractID(0)
rev := types.FileContractRevision{
ParentID: fcid,
UnlockConditions: uc,
NewFileSize: 10,
NewWindowStart: 100,
NewWindowEnd: 1000,
NewRevisionNumber: 1,
NewValidProofOutputs: fc.ValidProofOutputs,
NewMissedProofOutputs: fc.MissedProofOutputs,
}
// create transaction containing the revision
signedTxn := types.Transaction{
FileContractRevisions: []types.FileContractRevision{rev},
TransactionSignatures: []types.TransactionSignature{{
ParentID: crypto.Hash(fcid),
CoveredFields: types.CoveredFields{FileContractRevisions: []uint64{0}},
PublicKeyIndex: 0, // hostdb key is always first -- see negotiateContract
}},
}
// sign the transaction
encodedSig, err := crypto.SignHash(signedTxn.SigHash(0), sk)
if err != nil {
t.Fatal(err)
}
//.........這裏部分代碼省略.........
示例11: Renew
// Renew negotiates a new contract for data already stored with a host, and
// submits the new contract transaction to tpool.
func Renew(contract modules.RenterContract, params ContractParams, txnBuilder transactionBuilder, tpool transactionPool) (modules.RenterContract, error) {
// extract vars from params, for convenience
host, filesize, startHeight, endHeight, refundAddress := params.Host, params.Filesize, params.StartHeight, params.EndHeight, params.RefundAddress
ourSK := contract.SecretKey
// calculate cost to renter and cost to host
storageAllocation := host.StoragePrice.Mul64(filesize).Mul64(uint64(endHeight - startHeight))
hostCollateral := host.Collateral.Mul64(filesize).Mul64(uint64(endHeight - startHeight))
if hostCollateral.Cmp(host.MaxCollateral) > 0 {
// TODO: if we have to cap the collateral, it probably means we shouldn't be using this host
// (ok within a factor of 2)
hostCollateral = host.MaxCollateral
}
// Calculate additional basePrice and baseCollateral. If the contract
// height did not increase, basePrice and baseCollateral are zero.
var basePrice, baseCollateral types.Currency
if endHeight+host.WindowSize > contract.LastRevision.NewWindowEnd {
timeExtension := uint64((endHeight + host.WindowSize) - contract.LastRevision.NewWindowEnd)
basePrice = host.StoragePrice.Mul64(contract.LastRevision.NewFileSize).Mul64(timeExtension) // cost of data already covered by contract, i.e. lastrevision.Filesize
baseCollateral = host.Collateral.Mul64(contract.LastRevision.NewFileSize).Mul64(timeExtension) // same but collateral
}
hostPayout := hostCollateral.Add(host.ContractPrice).Add(basePrice)
payout := storageAllocation.Add(hostCollateral.Add(host.ContractPrice)).Mul64(10406).Div64(10000) // renter covers siafund fee
renterCost := payout.Sub(hostCollateral)
// check for negative currency
if types.PostTax(startHeight, payout).Cmp(hostPayout) < 0 {
return modules.RenterContract{}, errors.New("payout smaller than host payout")
} else if hostCollateral.Cmp(baseCollateral) < 0 {
return modules.RenterContract{}, errors.New("new collateral smaller than old collateral")
}
// create file contract
fc := types.FileContract{
FileSize: contract.LastRevision.NewFileSize,
FileMerkleRoot: contract.LastRevision.NewFileMerkleRoot,
WindowStart: endHeight,
WindowEnd: endHeight + host.WindowSize,
Payout: payout,
UnlockHash: contract.LastRevision.NewUnlockHash,
RevisionNumber: 0,
ValidProofOutputs: []types.SiacoinOutput{
// renter
{Value: types.PostTax(startHeight, payout).Sub(hostPayout), UnlockHash: refundAddress},
// host
{Value: hostPayout, UnlockHash: host.UnlockHash},
},
MissedProofOutputs: []types.SiacoinOutput{
// renter
{Value: types.PostTax(startHeight, payout).Sub(hostPayout), UnlockHash: refundAddress},
// host gets its unused collateral back, plus the contract price
{Value: hostCollateral.Sub(baseCollateral).Add(host.ContractPrice), UnlockHash: host.UnlockHash},
// void gets the spent storage fees, plus the collateral being risked
{Value: basePrice.Add(baseCollateral), UnlockHash: types.UnlockHash{}},
},
}
// calculate transaction fee
_, maxFee := tpool.FeeEstimation()
fee := maxFee.Mul64(estTxnSize)
// build transaction containing fc
err := txnBuilder.FundSiacoins(renterCost.Add(fee))
if err != nil {
return modules.RenterContract{}, err
}
txnBuilder.AddFileContract(fc)
// add miner fee
txnBuilder.AddMinerFee(fee)
// create initial transaction set
txn, parentTxns := txnBuilder.View()
txnSet := append(parentTxns, txn)
// initiate connection
conn, err := net.DialTimeout("tcp", string(host.NetAddress), 15*time.Second)
if err != nil {
return modules.RenterContract{}, err
}
defer func() { _ = conn.Close() }()
// allot time for sending RPC ID, verifyRecentRevision, and verifySettings
extendDeadline(conn, modules.NegotiateRecentRevisionTime+modules.NegotiateSettingsTime)
if err = encoding.WriteObject(conn, modules.RPCRenewContract); err != nil {
return modules.RenterContract{}, errors.New("couldn't initiate RPC: " + err.Error())
}
// verify that both parties are renewing the same contract
if err = verifyRecentRevision(conn, contract); err != nil {
return modules.RenterContract{}, errors.New("revision exchange failed: " + err.Error())
}
// verify the host's settings and confirm its identity
host, err = verifySettings(conn, host)
if err != nil {
return modules.RenterContract{}, errors.New("settings exchange failed: " + err.Error())
}
//.........這裏部分代碼省略.........
示例12: testFileContractRevision
// testFileContractRevision creates and revises a file contract on the
// blockchain.
func (cst *consensusSetTester) testFileContractRevision() {
// COMPATv0.4.0 - Step the block height up past the hardfork amount. This
// code stops nondeterministic failures when producing storage proofs that
// is related to buggy old code.
for cst.cs.dbBlockHeight() <= 10 {
_, err := cst.miner.AddBlock()
if err != nil {
panic(err)
}
}
// Create a file (as a bytes.Buffer) that will be used for the file
// contract.
filesize := uint64(4e3)
file := randFile(filesize)
merkleRoot, err := crypto.ReaderMerkleRoot(file)
if err != nil {
panic(err)
}
file.Seek(0, 0)
// Create a spendable unlock hash for the file contract.
sk, pk, err := crypto.GenerateKeyPair()
if err != nil {
panic(err)
}
uc := types.UnlockConditions{
PublicKeys: []types.SiaPublicKey{{
Algorithm: types.SignatureEd25519,
Key: pk[:],
}},
SignaturesRequired: 1,
}
// Create a file contract that will be revised.
validProofDest := randAddress()
payout := types.NewCurrency64(400e6)
fc := types.FileContract{
FileSize: filesize,
FileMerkleRoot: crypto.Hash{},
WindowStart: cst.cs.dbBlockHeight() + 2,
WindowEnd: cst.cs.dbBlockHeight() + 3,
Payout: payout,
ValidProofOutputs: []types.SiacoinOutput{{
UnlockHash: validProofDest,
Value: types.PostTax(cst.cs.dbBlockHeight(), payout),
}},
MissedProofOutputs: []types.SiacoinOutput{{
UnlockHash: types.UnlockHash{},
Value: types.PostTax(cst.cs.dbBlockHeight(), payout),
}},
UnlockHash: uc.UnlockHash(),
}
// Submit a transaction with the file contract.
txnBuilder := cst.wallet.StartTransaction()
err = txnBuilder.FundSiacoins(payout)
if err != nil {
panic(err)
}
fcIndex := txnBuilder.AddFileContract(fc)
txnSet, err := txnBuilder.Sign(true)
if err != nil {
panic(err)
}
err = cst.tpool.AcceptTransactionSet(txnSet)
if err != nil {
panic(err)
}
_, err = cst.miner.AddBlock()
if err != nil {
panic(err)
}
// Submit a revision for the file contract.
ti := len(txnSet) - 1
fcid := txnSet[ti].FileContractID(fcIndex)
fcr := types.FileContractRevision{
ParentID: fcid,
UnlockConditions: uc,
NewRevisionNumber: 69292,
NewFileSize: filesize,
NewFileMerkleRoot: merkleRoot,
NewWindowStart: cst.cs.dbBlockHeight() + 1,
NewWindowEnd: cst.cs.dbBlockHeight() + 2,
NewValidProofOutputs: fc.ValidProofOutputs,
NewMissedProofOutputs: fc.MissedProofOutputs,
NewUnlockHash: uc.UnlockHash(),
}
ts := types.TransactionSignature{
ParentID: crypto.Hash(fcid),
CoveredFields: types.CoveredFields{WholeTransaction: true},
PublicKeyIndex: 0,
}
txn := types.Transaction{
FileContractRevisions: []types.FileContractRevision{fcr},
TransactionSignatures: []types.TransactionSignature{ts},
//.........這裏部分代碼省略.........
示例13: FormContract
// FormContract forms a contract with a host and submits the contract
// transaction to tpool.
func FormContract(params ContractParams, txnBuilder transactionBuilder, tpool transactionPool) (modules.RenterContract, error) {
// extract vars from params, for convenience
host, filesize, startHeight, endHeight, refundAddress := params.Host, params.Filesize, params.StartHeight, params.EndHeight, params.RefundAddress
// create our key
ourSK, ourPK, err := crypto.GenerateKeyPair()
if err != nil {
return modules.RenterContract{}, err
}
ourPublicKey := types.SiaPublicKey{
Algorithm: types.SignatureEd25519,
Key: ourPK[:],
}
// create unlock conditions
uc := types.UnlockConditions{
PublicKeys: []types.SiaPublicKey{ourPublicKey, host.PublicKey},
SignaturesRequired: 2,
}
// calculate cost to renter and cost to host
// TODO: clarify/abstract this math
storageAllocation := host.StoragePrice.Mul64(filesize).Mul64(uint64(endHeight - startHeight))
hostCollateral := host.Collateral.Mul64(filesize).Mul64(uint64(endHeight - startHeight))
if hostCollateral.Cmp(host.MaxCollateral) > 0 {
// TODO: if we have to cap the collateral, it probably means we shouldn't be using this host
// (ok within a factor of 2)
hostCollateral = host.MaxCollateral
}
hostPayout := hostCollateral.Add(host.ContractPrice)
payout := storageAllocation.Add(hostPayout).Mul64(10406).Div64(10000) // renter pays for siafund fee
renterCost := payout.Sub(hostCollateral)
// check for negative currency
if types.PostTax(startHeight, payout).Cmp(hostPayout) < 0 {
return modules.RenterContract{}, errors.New("payout smaller than host payout")
}
// create file contract
fc := types.FileContract{
FileSize: 0,
FileMerkleRoot: crypto.Hash{}, // no proof possible without data
WindowStart: endHeight,
WindowEnd: endHeight + host.WindowSize,
Payout: payout,
UnlockHash: uc.UnlockHash(),
RevisionNumber: 0,
ValidProofOutputs: []types.SiacoinOutput{
// outputs need to account for tax
{Value: types.PostTax(startHeight, payout).Sub(hostPayout), UnlockHash: refundAddress},
// collateral is returned to host
{Value: hostPayout, UnlockHash: host.UnlockHash},
},
MissedProofOutputs: []types.SiacoinOutput{
// same as above
{Value: types.PostTax(startHeight, payout).Sub(hostPayout), UnlockHash: refundAddress},
// same as above
{Value: hostPayout, UnlockHash: host.UnlockHash},
// once we start doing revisions, we'll move some coins to the host and some to the void
{Value: types.ZeroCurrency, UnlockHash: types.UnlockHash{}},
},
}
// calculate transaction fee
_, maxFee := tpool.FeeEstimation()
fee := maxFee.Mul64(estTxnSize)
// build transaction containing fc
err = txnBuilder.FundSiacoins(renterCost.Add(fee))
if err != nil {
return modules.RenterContract{}, err
}
txnBuilder.AddFileContract(fc)
// add miner fee
txnBuilder.AddMinerFee(fee)
// create initial transaction set
txn, parentTxns := txnBuilder.View()
txnSet := append(parentTxns, txn)
// initiate connection
conn, err := net.DialTimeout("tcp", string(host.NetAddress), 15*time.Second)
if err != nil {
return modules.RenterContract{}, err
}
defer func() { _ = conn.Close() }()
// allot time for sending RPC ID + verifySettings
extendDeadline(conn, modules.NegotiateSettingsTime)
if err = encoding.WriteObject(conn, modules.RPCFormContract); err != nil {
return modules.RenterContract{}, err
}
// verify the host's settings and confirm its identity
host, err = verifySettings(conn, host)
if err != nil {
return modules.RenterContract{}, err
}
//.........這裏部分代碼省略.........
示例14: considerRevision
// considerRevision checks that the provided file contract revision is still
// acceptable to the host.
func (h *Host) considerRevision(txn types.Transaction, obligation *contractObligation) error {
// Check that there is only one revision.
if len(txn.FileContractRevisions) != 1 {
return errors.New("transaction should have only one revision")
}
// calculate minimum expected output value
rev := txn.FileContractRevisions[0]
duration := types.NewCurrency64(uint64(obligation.windowStart() - h.blockHeight))
sizeDiff := rev.NewFileSize - obligation.fileSize()
priceAdd := types.NewCurrency64(sizeDiff).Mul(duration).Mul(h.settings.Price)
minPayment := obligation.value().Add(priceAdd)
expectedPayout := types.PostTax(h.blockHeight, obligation.payout())
switch {
// Check that the revision matches the previous file contract.
case rev.ParentID != obligation.ID:
return errors.New("bad revision parent ID")
case rev.NewRevisionNumber <= obligation.revisionNumber():
return errors.New("revision must have higher revision number")
case rev.NewUnlockHash != obligation.unlockHash():
return errors.New("bad revision unlock hash")
case rev.UnlockConditions.UnlockHash() != obligation.unlockHash():
return errors.New("bad revision unlock conditions")
// Check that the window is unchanged.
case rev.NewWindowStart != obligation.windowStart():
return errors.New("bad revision window start")
case rev.NewWindowEnd != obligation.windowEnd():
return errors.New("bad revision window end")
// Check that the change in filesize is legal.
//
// TODO: Revisions should leave enough headroom so that renewals always
// have some space.
case rev.NewFileSize <= obligation.fileSize():
return errors.New("revision must add data")
case rev.NewFileSize-obligation.fileSize() > uint64(h.spaceRemaining):
return ErrHostCapacity
case rev.NewFileSize-obligation.fileSize() > maxRevisionSize:
return errors.New("revision adds too much data")
// Check that the payout information is correct.
case len(rev.NewValidProofOutputs) != 2:
return errors.New("bad revision valid proof outputs")
case len(rev.NewMissedProofOutputs) != 2:
return errors.New("bad revision missed proof outputs")
case rev.NewValidProofOutputs[1].UnlockHash != obligation.validProofUnlockHash(),
rev.NewMissedProofOutputs[1].UnlockHash != obligation.missedProofUnlockHash():
return errors.New("bad revision proof outputs")
case rev.NewValidProofOutputs[0].Value.Add(rev.NewValidProofOutputs[1].Value).Cmp(expectedPayout) != 0,
rev.NewMissedProofOutputs[0].Value.Add(rev.NewMissedProofOutputs[1].Value).Cmp(expectedPayout) != 0:
return errors.New("revision outputs do not sum to original payout")
case rev.NewValidProofOutputs[1].Value.Cmp(minPayment) < 0:
return ErrLowPayment
case rev.NewMissedProofOutputs[0].Value.Cmp(rev.NewValidProofOutputs[0].Value) != 0:
return errors.New("revision missed renter payout does not match valid payout")
}
return nil
}
示例15: considerContract
// considerContract checks that the provided transaction matches the host's
// terms, and doesn't contain any flagrant errors.
func (h *Host) considerContract(txn types.Transaction, renterKey types.SiaPublicKey, filesize uint64, merkleRoot crypto.Hash) error {
// Check that there is only one file contract.
if len(txn.FileContracts) != 1 {
return errors.New("transaction should have only one file contract")
}
// convenience variables
fc := txn.FileContracts[0]
duration := fc.WindowStart - h.blockHeight
minPayment := types.NewCurrency64(filesize).Mul(types.NewCurrency64(uint64(duration))).Mul(h.settings.Price)
expectedOutputSum := types.PostTax(h.blockHeight, fc.Payout)
// check contract fields for sanity and acceptability
switch {
// Check for legal filesize and content.
case fc.FileSize != filesize:
return errors.New("bad initial file size")
case fc.FileSize >= uint64(h.spaceRemaining):
return ErrHostCapacity
case fc.FileMerkleRoot != merkleRoot:
return errors.New("bad file contract Merkle root")
// Check for legal duration and proof window.
case fc.WindowStart <= h.blockHeight:
return errors.New("window start cannot be in the past")
case duration < h.settings.MinDuration || duration > h.settings.MaxDuration:
return errors.New("duration is out of bounds")
case fc.WindowEnd <= fc.WindowStart:
return errors.New("window cannot end before it starts")
case fc.WindowEnd-fc.WindowStart < h.settings.WindowSize:
return errors.New("challenge window is not large enough")
// Check for legal payout.
case fc.Payout.IsZero():
return errors.New("bad file contract payout")
case len(fc.ValidProofOutputs) != 2:
return errors.New("bad file contract valid proof outputs")
case len(fc.MissedProofOutputs) != 2:
return errors.New("bad file contract missed proof outputs")
case fc.ValidProofOutputs[0].Value.Add(fc.ValidProofOutputs[1].Value).Cmp(expectedOutputSum) != 0,
fc.MissedProofOutputs[0].Value.Add(fc.MissedProofOutputs[1].Value).Cmp(expectedOutputSum) != 0:
return errors.New("file contract outputs do not sum to original payout")
case fc.ValidProofOutputs[1].UnlockHash != h.settings.UnlockHash:
return errors.New("file contract valid proof output not sent to host")
case fc.ValidProofOutputs[1].Value.Cmp(minPayment) < 0:
return ErrLowPayment
case fc.MissedProofOutputs[0].Value.Cmp(fc.ValidProofOutputs[0].Value) != 0:
return errors.New("file contract missed renter payout does not match valid payout")
case fc.MissedProofOutputs[1].UnlockHash != (types.UnlockHash{}):
return errors.New("file contract missed proof output not sent to void")
}
// check unlock hash
uc := types.UnlockConditions{
PublicKeys: []types.SiaPublicKey{renterKey, h.publicKey},
SignaturesRequired: 2,
}
if fc.UnlockHash != uc.UnlockHash() {
return errors.New("bad file contract unlock hash")
}
return nil
}