本文整理匯總了Golang中github.com/NebulousLabs/Sia/crypto.Hash函數的典型用法代碼示例。如果您正苦於以下問題:Golang Hash函數的具體用法?Golang Hash怎麽用?Golang Hash使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了Hash函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: managedVerifyChallengeResponse
// managedVerifyChallengeResponse will verify that the renter's response to the
// challenge provided by the host is correct. In the process, the storage
// obligation and file contract revision will be loaded and returned.
//
// The storage obligation is returned under a storage obligation lock.
func (h *Host) managedVerifyChallengeResponse(fcid types.FileContractID, challenge crypto.Hash, challengeResponse crypto.Signature) (so storageObligation, recentRevision types.FileContractRevision, revisionSigs []types.TransactionSignature, err error) {
// Grab a lock before it is possible to perform any operations on the
// storage obligation. Defer a call to unlock in the event of an error. If
// there is no error, the storage obligation will be returned with a lock.
err = h.managedTryLockStorageObligation(fcid)
if err != nil {
err = extendErr("could not get "+fcid.String()+" lock: ", ErrorInternal(err.Error()))
return storageObligation{}, types.FileContractRevision{}, nil, err
}
defer func() {
if err != nil {
h.managedUnlockStorageObligation(fcid)
}
}()
// Fetch the storage obligation, which has the revision, which has the
// renter's public key.
h.mu.RLock()
defer h.mu.RUnlock()
err = h.db.View(func(tx *bolt.Tx) error {
so, err = getStorageObligation(tx, fcid)
return err
})
if err != nil {
err = extendErr("could not fetch "+fcid.String()+": ", ErrorInternal(err.Error()))
return storageObligation{}, types.FileContractRevision{}, nil, err
}
// Pull out the file contract revision and the revision's signatures from
// the transaction.
revisionTxn := so.RevisionTransactionSet[len(so.RevisionTransactionSet)-1]
recentRevision = revisionTxn.FileContractRevisions[0]
for _, sig := range revisionTxn.TransactionSignatures {
// Checking for just the parent id is sufficient, an over-signed file
// contract is invalid.
if sig.ParentID == crypto.Hash(fcid) {
revisionSigs = append(revisionSigs, sig)
}
}
// Verify that the challegne response matches the public key.
var renterPK crypto.PublicKey
// Sanity check - there should be two public keys.
if len(recentRevision.UnlockConditions.PublicKeys) != 2 {
// The error has to be set here so that the defered error check will
// unlock the storage obligation.
h.log.Critical("wrong public key count in file contract revision")
err = errRevisionWrongPublicKeyCount
err = extendErr("wrong public key count for "+fcid.String()+": ", ErrorInternal(err.Error()))
return storageObligation{}, types.FileContractRevision{}, nil, err
}
copy(renterPK[:], recentRevision.UnlockConditions.PublicKeys[0].Key)
err = crypto.VerifyHash(challenge, renterPK, challengeResponse)
if err != nil {
err = extendErr("bad signature from renter: ", ErrorCommunication(err.Error()))
return storageObligation{}, types.FileContractRevision{}, nil, err
}
return so, recentRevision, revisionSigs, nil
}
示例2: negotiateRevision
// negotiateRevision sends a revision and actions to the host for approval,
// completing one iteration of the revision loop.
func negotiateRevision(conn net.Conn, rev types.FileContractRevision, secretKey crypto.SecretKey) (types.Transaction, error) {
// create transaction containing the revision
signedTxn := types.Transaction{
FileContractRevisions: []types.FileContractRevision{rev},
TransactionSignatures: []types.TransactionSignature{{
ParentID: crypto.Hash(rev.ParentID),
CoveredFields: types.CoveredFields{FileContractRevisions: []uint64{0}},
PublicKeyIndex: 0, // renter key is always first -- see formContract
}},
}
// sign the transaction
encodedSig, _ := crypto.SignHash(signedTxn.SigHash(0), secretKey) // no error possible
signedTxn.TransactionSignatures[0].Signature = encodedSig[:]
// send the revision
if err := encoding.WriteObject(conn, rev); err != nil {
return types.Transaction{}, errors.New("couldn't send revision: " + err.Error())
}
// read acceptance
if err := modules.ReadNegotiationAcceptance(conn); err != nil {
return types.Transaction{}, errors.New("host did not accept revision: " + err.Error())
}
// send the new transaction signature
if err := encoding.WriteObject(conn, signedTxn.TransactionSignatures[0]); err != nil {
return types.Transaction{}, errors.New("couldn't send transaction signature: " + err.Error())
}
// read the host's acceptance and transaction signature
// NOTE: if the host sends ErrStopResponse, we should continue processing
// the revision, but return the error anyway.
responseErr := modules.ReadNegotiationAcceptance(conn)
if responseErr != nil && responseErr != modules.ErrStopResponse {
return types.Transaction{}, errors.New("host did not accept transaction signature: " + responseErr.Error())
}
var hostSig types.TransactionSignature
if err := encoding.ReadObject(conn, &hostSig, 16e3); err != nil {
return types.Transaction{}, errors.New("couldn't read host's signature: " + err.Error())
}
// add the signature to the transaction and verify it
// NOTE: we can fake the blockheight here because it doesn't affect
// verification; it just needs to be above the fork height and below the
// contract expiration (which was checked earlier).
verificationHeight := rev.NewWindowStart - 1
signedTxn.TransactionSignatures = append(signedTxn.TransactionSignatures, hostSig)
if err := signedTxn.StandaloneValid(verificationHeight); err != nil {
return types.Transaction{}, err
}
// if the host sent ErrStopResponse, return it
return signedTxn, responseErr
}
示例3: storageSectorsDeleteHandler
// storageSectorsDeleteHandler handles the call to delete a sector from the
// storage manager.
func (srv *Server) storageSectorsDeleteHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
sectorRoot, err := scanAddress(ps.ByName("merkleroot"))
if err != nil {
writeError(w, Error{err.Error()}, http.StatusBadRequest)
return
}
err = srv.host.DeleteSector(crypto.Hash(sectorRoot))
if err != nil {
writeError(w, Error{err.Error()}, http.StatusBadRequest)
return
}
writeSuccess(w)
}
示例4: addAddress
// addAddress either creates a new list of transactions for the given
// address, or adds the txid to the list if such a list already exists
func (tx *boltTx) addAddress(addr types.UnlockHash, txid types.TransactionID) {
tx.putObject("Hashes", crypto.Hash(addr), hashUnlockHash)
oldErr := tx.err
var txns []types.TransactionID
tx.getObject("Addresses", addr, &txns)
if oldErr == nil && tx.err == persist.ErrNilEntry {
// NOTE: this is a special case where a nil entry is not an error, so
// we must explicitly reset tx.err.
tx.err = nil
}
txns = append(txns, txid)
tx.putObject("Addresses", addr, txns)
}
示例5: negotiateRevision
// negotiateRevision sends the revision and new piece data to the host.
func negotiateRevision(conn net.Conn, rev types.FileContractRevision, piece []byte, secretKey crypto.SecretKey) (types.Transaction, error) {
conn.SetDeadline(time.Now().Add(5 * time.Minute)) // sufficient to transfer 4 MB over 100 kbps
defer conn.SetDeadline(time.Time{}) // reset timeout after each revision
// create transaction containing the revision
signedTxn := types.Transaction{
FileContractRevisions: []types.FileContractRevision{rev},
TransactionSignatures: []types.TransactionSignature{{
ParentID: crypto.Hash(rev.ParentID),
CoveredFields: types.CoveredFields{FileContractRevisions: []uint64{0}},
PublicKeyIndex: 0, // renter key is always first -- see negotiateContract
}},
}
// sign the transaction
encodedSig, _ := crypto.SignHash(signedTxn.SigHash(0), secretKey) // no error possible
signedTxn.TransactionSignatures[0].Signature = encodedSig[:]
// send the transaction
if err := encoding.WriteObject(conn, signedTxn); err != nil {
return types.Transaction{}, errors.New("couldn't send revision transaction: " + err.Error())
}
// host sends acceptance
var response string
if err := encoding.ReadObject(conn, &response, 128); err != nil {
return types.Transaction{}, errors.New("couldn't read host acceptance: " + err.Error())
}
if response != modules.AcceptResponse {
return types.Transaction{}, errors.New("host rejected revision: " + response)
}
// transfer piece
if _, err := conn.Write(piece); err != nil {
return types.Transaction{}, errors.New("couldn't transfer piece: " + err.Error())
}
// read txn signed by host
var signedHostTxn types.Transaction
if err := encoding.ReadObject(conn, &signedHostTxn, types.BlockSizeLimit); err != nil {
return types.Transaction{}, errors.New("couldn't read signed revision transaction: " + err.Error())
}
if signedHostTxn.ID() != signedTxn.ID() {
return types.Transaction{}, errors.New("host sent bad signed transaction")
}
return signedHostTxn, nil
}
示例6: TestIDs
// TestTransactionIDs probes all of the ID functions of the Transaction type.
func TestIDs(t *testing.T) {
// Create every type of ID using empty fields.
txn := Transaction{
SiacoinOutputs: []SiacoinOutput{{}},
FileContracts: []FileContract{{}},
SiafundOutputs: []SiafundOutput{{}},
}
tid := txn.ID()
scoid := txn.SiacoinOutputID(0)
fcid := txn.FileContractID(0)
fctpid := fcid.FileContractTerminationPayoutID(0)
spidT := fcid.StorageProofOutputID(ProofValid, 0)
spidF := fcid.StorageProofOutputID(ProofMissed, 0)
sfoid := txn.SiafundOutputID(0)
scloid := sfoid.SiaClaimOutputID()
// Put all of the ids into a slice.
var ids []crypto.Hash
ids = append(ids,
crypto.Hash(tid),
crypto.Hash(scoid),
crypto.Hash(fcid),
crypto.Hash(fctpid),
crypto.Hash(spidT),
crypto.Hash(spidF),
crypto.Hash(sfoid),
crypto.Hash(scloid),
)
// Check that each id is unique.
knownIDs := make(map[crypto.Hash]struct{})
for i, id := range ids {
_, exists := knownIDs[id]
if exists {
t.Error("id repeat for index", i)
}
knownIDs[id] = struct{}{}
}
}
示例7: verifyChallengeResponse
// verifyChallengeResponse will verify that the renter's response to the
// challenge provided by the host is correct. In the process, the storage
// obligation and file contract revision will be loaded and returned.
func (h *Host) verifyChallengeResponse(fcid types.FileContractID, challenge crypto.Hash, challengeResponse crypto.Signature) (*storageObligation, types.FileContractRevision, []types.TransactionSignature, error) {
// Fetch the storage obligation, which has the revision, which has the
// renter's public key.
var so *storageObligation
err := h.db.Update(func(tx *bolt.Tx) error {
fso, err := getStorageObligation(tx, fcid)
so = &fso
return err
})
if err != nil {
return nil, types.FileContractRevision{}, nil, err
}
// Pull out the file contract revision and the revision's signatures from
// the transaction.
revisionTxn := so.RevisionTransactionSet[len(so.RevisionTransactionSet)-1]
recentRevision := revisionTxn.FileContractRevisions[0]
var revisionSigs []types.TransactionSignature
for _, sig := range revisionTxn.TransactionSignatures {
// Checking for just the parent id is sufficient, an over-signed file
// contract is invalid.
if sig.ParentID == crypto.Hash(fcid) {
revisionSigs = append(revisionSigs, sig)
}
}
// Verify that the challegne response matches the public key.
var renterPK crypto.PublicKey
// Sanity check - there should be two public keys.
if len(recentRevision.UnlockConditions.PublicKeys) != 2 {
h.log.Critical("found a revision with too few public keys")
return nil, types.FileContractRevision{}, nil, errRevisionFewPublicKeys
}
copy(renterPK[:], recentRevision.UnlockConditions.PublicKeys[0].Key)
err = crypto.VerifyHash(challenge, renterPK, challengeResponse)
if err != nil {
return nil, types.FileContractRevision{}, nil, err
}
return so, recentRevision, revisionSigs, nil
}
示例8: createRevisionSignature
// createRevisionSignature creates a signature for a file contract revision
// that signs on the file contract revision. The renter should have already
// provided the signature. createRevisionSignature will check to make sure that
// the renter's signature is valid.
func createRevisionSignature(fcr types.FileContractRevision, renterSig types.TransactionSignature, secretKey crypto.SecretKey, blockHeight types.BlockHeight) (types.Transaction, error) {
hostSig := types.TransactionSignature{
ParentID: crypto.Hash(fcr.ParentID),
PublicKeyIndex: 1,
CoveredFields: types.CoveredFields{
FileContractRevisions: []uint64{0},
},
}
txn := types.Transaction{
FileContractRevisions: []types.FileContractRevision{fcr},
TransactionSignatures: []types.TransactionSignature{renterSig, hostSig},
}
sigHash := txn.SigHash(1)
encodedSig, err := crypto.SignHash(sigHash, secretKey)
if err != nil {
return types.Transaction{}, err
}
txn.TransactionSignatures[1].Signature = encodedSig[:]
err = modules.VerifyFileContractRevisionTransactionSignatures(fcr, txn.TransactionSignatures, blockHeight)
if err != nil {
return types.Transaction{}, err
}
return txn, nil
}
示例9: validSignatures
// validSignatures checks the validaty of all signatures in a transaction.
func (t *Transaction) validSignatures(currentHeight BlockHeight) error {
// Check that all covered fields objects follow the rules.
err := t.validCoveredFields()
if err != nil {
return err
}
// Create the inputSignatures object for each input.
sigMap := make(map[crypto.Hash]*inputSignatures)
for i, input := range t.SiacoinInputs {
id := crypto.Hash(input.ParentID)
_, exists := sigMap[id]
if exists {
return ErrDoubleSpend
}
sigMap[id] = &inputSignatures{
remainingSignatures: input.UnlockConditions.SignaturesRequired,
possibleKeys: input.UnlockConditions.PublicKeys,
usedKeys: make(map[uint64]struct{}),
index: i,
}
}
for i, revision := range t.FileContractRevisions {
id := crypto.Hash(revision.ParentID)
_, exists := sigMap[id]
if exists {
return ErrDoubleSpend
}
sigMap[id] = &inputSignatures{
remainingSignatures: revision.UnlockConditions.SignaturesRequired,
possibleKeys: revision.UnlockConditions.PublicKeys,
usedKeys: make(map[uint64]struct{}),
index: i,
}
}
for i, input := range t.SiafundInputs {
id := crypto.Hash(input.ParentID)
_, exists := sigMap[id]
if exists {
return ErrDoubleSpend
}
sigMap[id] = &inputSignatures{
remainingSignatures: input.UnlockConditions.SignaturesRequired,
possibleKeys: input.UnlockConditions.PublicKeys,
usedKeys: make(map[uint64]struct{}),
index: i,
}
}
// Check all of the signatures for validity.
for i, sig := range t.TransactionSignatures {
// Check that sig corresponds to an entry in sigMap.
inSig, exists := sigMap[crypto.Hash(sig.ParentID)]
if !exists || inSig.remainingSignatures == 0 {
return ErrFrivilousSignature
}
// Check that sig's key hasn't already been used.
_, exists = inSig.usedKeys[sig.PublicKeyIndex]
if exists {
return ErrPublicKeyOveruse
}
// Check that the public key index refers to an existing public key.
if sig.PublicKeyIndex >= uint64(len(inSig.possibleKeys)) {
return ErrInvalidPubKeyIndex
}
// Check that the timelock has expired.
if sig.Timelock > currentHeight {
return ErrPrematureSignature
}
// Check that the signature verifies. Multiple signature schemes are
// supported.
publicKey := inSig.possibleKeys[sig.PublicKeyIndex]
switch publicKey.Algorithm {
case SignatureEntropy:
// Entropy cannot ever be used to sign a transaction.
return ErrEntropyKey
case SignatureEd25519:
// Decode the public key and signature.
var edPK crypto.PublicKey
err := encoding.Unmarshal([]byte(publicKey.Key), &edPK)
if err != nil {
return err
}
var edSig [crypto.SignatureSize]byte
err = encoding.Unmarshal([]byte(sig.Signature), &edSig)
if err != nil {
return err
}
cryptoSig := crypto.Signature(edSig)
sigHash := t.SigHash(i)
err = crypto.VerifyHash(sigHash, edPK, cryptoSig)
if err != nil {
return err
//.........這裏部分代碼省略.........
示例10: revise
// revise revises fc to cover piece and uploads both the revision and the
// piece data to the host.
func (hu *hostUploader) revise(fc types.FileContract, piece []byte, height types.BlockHeight) error {
hu.conn.SetDeadline(time.Now().Add(5 * time.Minute)) // sufficient to transfer 4 MB over 100 kbps
defer hu.conn.SetDeadline(time.Time{}) // reset timeout after each revision
// calculate new merkle root
err := hu.tree.ReadSegments(bytes.NewReader(piece))
if err != nil {
return err
}
// create revision
rev := types.FileContractRevision{
ParentID: hu.contract.ID,
UnlockConditions: hu.unlockConditions,
NewRevisionNumber: fc.RevisionNumber + 1,
NewFileSize: fc.FileSize + uint64(len(piece)),
NewFileMerkleRoot: hu.tree.Root(),
NewWindowStart: fc.WindowStart,
NewWindowEnd: fc.WindowEnd,
NewValidProofOutputs: fc.ValidProofOutputs,
NewMissedProofOutputs: fc.MissedProofOutputs,
NewUnlockHash: fc.UnlockHash,
}
// transfer value of piece from renter to host
safeDuration := uint64(fc.WindowStart - height + 20) // buffer in case host is behind
piecePrice := types.NewCurrency64(uint64(len(piece))).Mul(types.NewCurrency64(safeDuration)).Mul(hu.settings.Price)
// prevent a negative currency panic
if piecePrice.Cmp(fc.ValidProofOutputs[0].Value) > 0 {
// probably not enough money, but the host might accept it anyway
piecePrice = fc.ValidProofOutputs[0].Value
}
rev.NewValidProofOutputs[0].Value = rev.NewValidProofOutputs[0].Value.Sub(piecePrice) // less returned to renter
rev.NewValidProofOutputs[1].Value = rev.NewValidProofOutputs[1].Value.Add(piecePrice) // more given to host
rev.NewMissedProofOutputs[0].Value = rev.NewMissedProofOutputs[0].Value.Sub(piecePrice) // less returned to renter
rev.NewMissedProofOutputs[1].Value = rev.NewMissedProofOutputs[1].Value.Add(piecePrice) // more given to void
// create transaction containing the revision
signedTxn := types.Transaction{
FileContractRevisions: []types.FileContractRevision{rev},
TransactionSignatures: []types.TransactionSignature{{
ParentID: crypto.Hash(hu.contract.ID),
CoveredFields: types.CoveredFields{FileContractRevisions: []uint64{0}},
PublicKeyIndex: 0, // renter key is always first -- see negotiateContract
}},
}
// sign the transaction
encodedSig, err := crypto.SignHash(signedTxn.SigHash(0), hu.secretKey)
if err != nil {
return err
}
signedTxn.TransactionSignatures[0].Signature = encodedSig[:]
// send the transaction
if err := encoding.WriteObject(hu.conn, signedTxn); err != nil {
return err
}
// host sends acceptance
var response string
if err := encoding.ReadObject(hu.conn, &response, 128); err != nil {
return err
}
if response != modules.AcceptResponse {
return errors.New("host rejected revision: " + response)
}
// transfer piece
if _, err := hu.conn.Write(piece); err != nil {
return err
}
// read txn signed by host
var signedHostTxn types.Transaction
if err := encoding.ReadObject(hu.conn, &signedHostTxn, types.BlockSizeLimit); err != nil {
return err
}
if signedHostTxn.ID() != signedTxn.ID() {
return errors.New("host sent bad signed transaction")
} else if err = signedHostTxn.StandaloneValid(height); err != nil {
return err
}
hu.lastTxn = signedHostTxn
return nil
}
示例11: SendSiagSiafunds
// SendSiagSiafunds sends siafunds to another address. The siacoins stored in
// the siafunds are sent to an address in the wallet.
func (w *Wallet) SendSiagSiafunds(amount types.Currency, dest types.UnlockHash, keyfiles []string) (types.Transaction, error) {
if len(keyfiles) < 1 {
return types.Transaction{}, ErrNoKeyfile
}
// Load the siafund keys and verify they are sufficient to sign the
// transaction.
skps := make([]SiagKeyPair, len(keyfiles))
for i, keyfile := range keyfiles {
err := encoding.ReadFile(keyfile, &skps[i])
if err != nil {
return types.Transaction{}, err
}
if skps[i].Header != SiagFileHeader {
return types.Transaction{}, ErrUnknownHeader
}
if skps[i].Version != SiagFileVersion {
return types.Transaction{}, ErrUnknownVersion
}
}
// Check that all of the loaded files have the same address, and that there
// are enough to create the transaction.
baseUnlockHash := skps[0].UnlockConditions.UnlockHash()
for _, skp := range skps {
if skp.UnlockConditions.UnlockHash() != baseUnlockHash {
return types.Transaction{}, ErrInconsistentKeys
}
}
if uint64(len(skps)) < skps[0].UnlockConditions.SignaturesRequired {
return types.Transaction{}, ErrInsufficientKeys
}
// Check that there are enough siafunds in the key to complete the spend.
lockID := w.mu.RLock()
var availableSiafunds types.Currency
var sfoids []types.SiafundOutputID
for sfoid, sfo := range w.siafundOutputs {
if sfo.UnlockHash == baseUnlockHash {
availableSiafunds = availableSiafunds.Add(sfo.Value)
sfoids = append(sfoids, sfoid)
}
if availableSiafunds.Cmp(amount) >= 0 {
break
}
}
w.mu.RUnlock(lockID)
if availableSiafunds.Cmp(amount) < 0 {
return types.Transaction{}, ErrInsufficientSiafunds
}
// Truncate the keys to exactly the number needed.
skps = skps[:skps[0].UnlockConditions.SignaturesRequired]
// Assemble the base transction, including a 10 siacoin fee if possible.
id, err := w.RegisterTransaction(types.Transaction{})
if err != nil {
return types.Transaction{}, err
}
// Add a miner fee - if funding the transaction fails, we'll just send a
// transaction with no fee.
txn, err := w.FundTransaction(id, types.NewCurrency64(TransactionFee))
if err == nil {
txn, _, err = w.AddMinerFee(id, types.NewCurrency64(TransactionFee))
if err != nil {
return types.Transaction{}, err
}
}
// Add the siafund inputs to the transcation.
for _, sfoid := range sfoids {
// Get an address for the siafund claims.
lockID := w.mu.Lock()
claimDest, _, err := w.coinAddress(false)
w.mu.Unlock(lockID)
if err != nil {
return types.Transaction{}, err
}
// Assemble the SiafundInput to spend this output.
sfi := types.SiafundInput{
ParentID: sfoid,
UnlockConditions: skps[0].UnlockConditions,
ClaimUnlockHash: claimDest,
}
txn, _, err = w.AddSiafundInput(id, sfi)
if err != nil {
return types.Transaction{}, err
}
}
// Add the siafund output to the transaction.
sfo := types.SiafundOutput{
Value: amount,
UnlockHash: dest,
}
txn, _, err = w.AddSiafundOutput(id, sfo)
if err != nil {
return types.Transaction{}, err
//.........這裏部分代碼省略.........
示例12: managedRPCRevise
// managedRPCRevise is an RPC that allows a renter to revise a file contract. It will
// read new revisions in a loop until the renter sends a termination signal.
func (h *Host) managedRPCRevise(conn net.Conn) error {
// read ID of contract to be revised
var fcid types.FileContractID
if err := encoding.ReadObject(conn, &fcid, crypto.HashSize); err != nil {
return errors.New("couldn't read contract ID: " + err.Error())
}
// remove conn deadline while we wait for lock and rebuild the Merkle tree.
err := conn.SetDeadline(time.Now().Add(15 * time.Minute))
if err != nil {
return err
}
h.mu.RLock()
obligation, exists := h.obligationsByID[fcid]
h.mu.RUnlock()
if !exists {
return errors.New("no record of that contract")
}
// need to protect against two simultaneous revisions to the same
// contract; this can cause inconsistency and data loss, making storage
// proofs impossible
//
// TODO: DOS vector - the host has locked the obligation even though the
// renter has not proven themselves to be the owner of the file contract.
obligation.mu.Lock()
defer obligation.mu.Unlock()
// open the file in append mode
file, err := os.OpenFile(obligation.Path, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0660)
if err != nil {
return err
}
// rebuild current Merkle tree
tree := crypto.NewTree()
err = tree.ReadSegments(file)
if err != nil {
// Error does not need to be checked when closing the file, already
// there have been issues related to the filesystem.
_ = file.Close()
return err
}
// accept new revisions in a loop. The final good transaction will be
// submitted to the blockchain.
revisionErr := func() error {
for {
// allow 5 minutes between revisions
err := conn.SetDeadline(time.Now().Add(5 * time.Minute))
if err != nil {
return err
}
// read proposed revision
var revTxn types.Transaction
if err = encoding.ReadObject(conn, &revTxn, types.BlockSizeLimit); err != nil {
return errors.New("couldn't read revision: " + err.Error())
}
// an empty transaction indicates completion
if revTxn.ID() == (types.Transaction{}).ID() {
return nil
}
// allow 5 minutes for each revision
err = conn.SetDeadline(time.Now().Add(5 * time.Minute))
if err != nil {
return err
}
// check revision against original file contract
h.mu.RLock()
err = h.considerRevision(revTxn, obligation)
h.mu.RUnlock()
if err != nil {
// There is nothing that can be done if there is an error while
// writing to a connection.
_ = encoding.WriteObject(conn, err.Error())
return err
}
// indicate acceptance
if err := encoding.WriteObject(conn, modules.AcceptResponse); err != nil {
return errors.New("couldn't write acceptance: " + err.Error())
}
// read piece
// TODO: simultaneously read into tree and file
rev := revTxn.FileContractRevisions[0]
piece := make([]byte, rev.NewFileSize-obligation.fileSize())
_, err = io.ReadFull(conn, piece)
if err != nil {
return errors.New("couldn't read piece data: " + err.Error())
}
// verify Merkle root
err = tree.ReadSegments(bytes.NewReader(piece))
if err != nil {
//.........這裏部分代碼省略.........
示例13: FundSiacoins
// FundSiacoins will add a siacoin input of exaclty 'amount' to the
// transaction. A parent transaction may be needed to achieve an input with the
// correct value. The siacoin input will not be signed until 'Sign' is called
// on the transaction builder.
func (tb *transactionBuilder) FundSiacoins(amount types.Currency) error {
tb.wallet.mu.Lock()
defer tb.wallet.mu.Unlock()
// Collect a value-sorted set of siacoin outputs.
var so sortedOutputs
for scoid, sco := range tb.wallet.siacoinOutputs {
so.ids = append(so.ids, scoid)
so.outputs = append(so.outputs, sco)
}
// Add all of the unconfirmed outputs as well.
for _, upt := range tb.wallet.unconfirmedProcessedTransactions {
for i, sco := range upt.Transaction.SiacoinOutputs {
// Determine if the output belongs to the wallet.
_, exists := tb.wallet.keys[sco.UnlockHash]
if !exists {
continue
}
so.ids = append(so.ids, upt.Transaction.SiacoinOutputID(uint64(i)))
so.outputs = append(so.outputs, sco)
}
}
sort.Sort(sort.Reverse(so))
// Create and fund a parent transaction that will add the correct amount of
// siacoins to the transaction.
var fund types.Currency
// potentialFund tracks the balance of the wallet including outputs that
// have been spent in other unconfirmed transactions recently. This is to
// provide the user with a more useful error message in the event that they
// are overspending.
var potentialFund types.Currency
parentTxn := types.Transaction{}
var spentScoids []types.SiacoinOutputID
for i := range so.ids {
scoid := so.ids[i]
sco := so.outputs[i]
// Check that this output has not recently been spent by the wallet.
spendHeight := tb.wallet.spentOutputs[types.OutputID(scoid)]
// Prevent an underflow error.
allowedHeight := tb.wallet.consensusSetHeight - RespendTimeout
if tb.wallet.consensusSetHeight < RespendTimeout {
allowedHeight = 0
}
if spendHeight > allowedHeight {
potentialFund = potentialFund.Add(sco.Value)
continue
}
outputUnlockConditions := tb.wallet.keys[sco.UnlockHash].UnlockConditions
if tb.wallet.consensusSetHeight < outputUnlockConditions.Timelock {
continue
}
// Add a siacoin input for this output.
sci := types.SiacoinInput{
ParentID: scoid,
UnlockConditions: outputUnlockConditions,
}
parentTxn.SiacoinInputs = append(parentTxn.SiacoinInputs, sci)
spentScoids = append(spentScoids, scoid)
// Add the output to the total fund
fund = fund.Add(sco.Value)
potentialFund = potentialFund.Add(sco.Value)
if fund.Cmp(amount) >= 0 {
break
}
}
if potentialFund.Cmp(amount) >= 0 && fund.Cmp(amount) < 0 {
return modules.ErrPotentialDoubleSpend
}
if fund.Cmp(amount) < 0 {
return modules.ErrLowBalance
}
// Create and add the output that will be used to fund the standard
// transaction.
parentUnlockConditions, err := tb.wallet.nextPrimarySeedAddress()
if err != nil {
return err
}
exactOutput := types.SiacoinOutput{
Value: amount,
UnlockHash: parentUnlockConditions.UnlockHash(),
}
parentTxn.SiacoinOutputs = append(parentTxn.SiacoinOutputs, exactOutput)
// Create a refund output if needed.
if amount.Cmp(fund) != 0 {
refundUnlockConditions, err := tb.wallet.nextPrimarySeedAddress()
if err != nil {
return err
}
refundOutput := types.SiacoinOutput{
Value: fund.Sub(amount),
UnlockHash: refundUnlockConditions.UnlockHash(),
//.........這裏部分代碼省略.........
示例14: FundSiafunds
// FundSiafunds will add a siafund input of exaclty 'amount' to the
// transaction. A parent transaction may be needed to achieve an input with the
// correct value. The siafund input will not be signed until 'Sign' is called
// on the transaction builder.
func (tb *transactionBuilder) FundSiafunds(amount types.Currency) error {
tb.wallet.mu.Lock()
defer tb.wallet.mu.Unlock()
// Create and fund a parent transaction that will add the correct amount of
// siafunds to the transaction.
var fund types.Currency
var potentialFund types.Currency
parentTxn := types.Transaction{}
var spentSfoids []types.SiafundOutputID
for sfoid, sfo := range tb.wallet.siafundOutputs {
// Check that this output has not recently been spent by the wallet.
spendHeight := tb.wallet.spentOutputs[types.OutputID(sfoid)]
// Prevent an underflow error.
allowedHeight := tb.wallet.consensusSetHeight - RespendTimeout
if tb.wallet.consensusSetHeight < RespendTimeout {
allowedHeight = 0
}
if spendHeight > allowedHeight {
potentialFund = potentialFund.Add(sfo.Value)
continue
}
outputUnlockConditions := tb.wallet.keys[sfo.UnlockHash].UnlockConditions
if tb.wallet.consensusSetHeight < outputUnlockConditions.Timelock {
continue
}
// Add a siafund input for this output.
parentClaimUnlockConditions, err := tb.wallet.nextPrimarySeedAddress()
if err != nil {
return err
}
sfi := types.SiafundInput{
ParentID: sfoid,
UnlockConditions: outputUnlockConditions,
ClaimUnlockHash: parentClaimUnlockConditions.UnlockHash(),
}
parentTxn.SiafundInputs = append(parentTxn.SiafundInputs, sfi)
spentSfoids = append(spentSfoids, sfoid)
// Add the output to the total fund
fund = fund.Add(sfo.Value)
potentialFund = potentialFund.Add(sfo.Value)
if fund.Cmp(amount) >= 0 {
break
}
}
if potentialFund.Cmp(amount) >= 0 && fund.Cmp(amount) < 0 {
return modules.ErrPotentialDoubleSpend
}
if fund.Cmp(amount) < 0 {
return modules.ErrLowBalance
}
// Create and add the output that will be used to fund the standard
// transaction.
parentUnlockConditions, err := tb.wallet.nextPrimarySeedAddress()
if err != nil {
return err
}
exactOutput := types.SiafundOutput{
Value: amount,
UnlockHash: parentUnlockConditions.UnlockHash(),
}
parentTxn.SiafundOutputs = append(parentTxn.SiafundOutputs, exactOutput)
// Create a refund output if needed.
if amount.Cmp(fund) != 0 {
refundUnlockConditions, err := tb.wallet.nextPrimarySeedAddress()
if err != nil {
return err
}
refundOutput := types.SiafundOutput{
Value: fund.Sub(amount),
UnlockHash: refundUnlockConditions.UnlockHash(),
}
parentTxn.SiafundOutputs = append(parentTxn.SiafundOutputs, refundOutput)
}
// Sign all of the inputs to the parent trancstion.
for _, sfi := range parentTxn.SiafundInputs {
_, err := addSignatures(&parentTxn, types.FullCoveredFields, sfi.UnlockConditions, crypto.Hash(sfi.ParentID), tb.wallet.keys[sfi.UnlockConditions.UnlockHash()])
if err != nil {
return err
}
}
// Add the exact output.
claimUnlockConditions, err := tb.wallet.nextPrimarySeedAddress()
if err != nil {
return err
}
newInput := types.SiafundInput{
ParentID: parentTxn.SiafundOutputID(0),
UnlockConditions: parentUnlockConditions,
ClaimUnlockHash: claimUnlockConditions.UnlockHash(),
//.........這裏部分代碼省略.........
示例15: consensusSetHash
// consensusSetHash returns the Merkle root of the current state of consensus.
func (cs *ConsensusSet) consensusSetHash() crypto.Hash {
// Check is too slow to be done on a full node.
if build.Release == "standard" {
return crypto.Hash{}
}
// Items of interest:
// 1. genesis block
// 3. current height
// 4. current target
// 5. current depth
// 6. current path + diffs
// (7) earliest allowed timestamp of next block
// 8. unspent siacoin outputs, sorted by id.
// 9. open file contracts, sorted by id.
// 10. unspent siafund outputs, sorted by id.
// 11. delayed siacoin outputs, sorted by height, then sorted by id.
// 12. siafund pool
// Create a slice of hashes representing all items of interest.
tree := crypto.NewTree()
tree.PushObject(cs.blockRoot.Block)
tree.PushObject(cs.height())
tree.PushObject(cs.currentProcessedBlock().ChildTarget)
tree.PushObject(cs.currentProcessedBlock().Depth)
// tree.PushObject(cs.earliestChildTimestamp(cs.currentProcessedBlock()))
// Add all the blocks in the current path TODO: along with their diffs.
for i := 0; i < int(cs.db.pathHeight()); i++ {
tree.PushObject(cs.db.getPath(types.BlockHeight(i)))
}
// Add all of the siacoin outputs, sorted by id.
var openSiacoinOutputs crypto.HashSlice
cs.db.forEachSiacoinOutputs(func(scoid types.SiacoinOutputID, sco types.SiacoinOutput) {
openSiacoinOutputs = append(openSiacoinOutputs, crypto.Hash(scoid))
})
sort.Sort(openSiacoinOutputs)
for _, id := range openSiacoinOutputs {
sco := cs.db.getSiacoinOutputs(types.SiacoinOutputID(id))
tree.PushObject(id)
tree.PushObject(sco)
}
// Add all of the file contracts, sorted by id.
var openFileContracts crypto.HashSlice
cs.db.forEachFileContracts(func(fcid types.FileContractID, fc types.FileContract) {
openFileContracts = append(openFileContracts, crypto.Hash(fcid))
})
sort.Sort(openFileContracts)
for _, id := range openFileContracts {
// Sanity Check - file contract should exist.
fc := cs.db.getFileContracts(types.FileContractID(id))
tree.PushObject(id)
tree.PushObject(fc)
}
// Add all of the siafund outputs, sorted by id.
var openSiafundOutputs crypto.HashSlice
cs.db.forEachSiafundOutputs(func(sfoid types.SiafundOutputID, sfo types.SiafundOutput) {
openSiafundOutputs = append(openSiafundOutputs, crypto.Hash(sfoid))
})
sort.Sort(openSiafundOutputs)
for _, id := range openSiafundOutputs {
sco := cs.db.getSiafundOutputs(types.SiafundOutputID(id))
tree.PushObject(id)
tree.PushObject(sco)
}
// Get the set of delayed siacoin outputs, sorted by maturity height then
// sorted by id and add them.
for i := cs.height() + 1; i <= cs.height()+types.MaturityDelay; i++ {
var delayedSiacoinOutputs crypto.HashSlice
if cs.db.inDelayedSiacoinOutputs(i) {
cs.db.forEachDelayedSiacoinOutputsHeight(i, func(id types.SiacoinOutputID, output types.SiacoinOutput) {
delayedSiacoinOutputs = append(delayedSiacoinOutputs, crypto.Hash(id))
})
}
sort.Sort(delayedSiacoinOutputs)
for _, delayedSiacoinOutputID := range delayedSiacoinOutputs {
delayedSiacoinOutput := cs.db.getDelayedSiacoinOutputs(i, types.SiacoinOutputID(delayedSiacoinOutputID))
tree.PushObject(delayedSiacoinOutput)
tree.PushObject(delayedSiacoinOutputID)
}
}
// Add the siafund pool
var siafundPool types.Currency
err := cs.db.Update(func(tx *bolt.Tx) error {
siafundPool = getSiafundPool(tx)
return nil
})
if err != nil {
panic(err)
}
tree.PushObject(siafundPool)
return tree.Root()
}