本文整理匯總了Golang中github.com/NebulousLabs/Sia/crypto.SignHash函數的典型用法代碼示例。如果您正苦於以下問題:Golang SignHash函數的具體用法?Golang SignHash怎麽用?Golang SignHash使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了SignHash函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: 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
}
示例2: verifyKeysSiag_1_0
// verifyKeysSiag_1_0 is a copy-pasted version of the verifyKeys method
// from siag 1.0.
func verifyKeysSiag_1_0(uc types.UnlockConditions, folder string, keyname string) error {
keysRequired := uc.SignaturesRequired
totalKeys := uint64(len(uc.PublicKeys))
loadedKeys := make([]KeyPairSiag_1_0, totalKeys)
for i := 0; i < len(loadedKeys); i++ {
err := encoding.ReadFile(filepath.Join(folder, keyname+"_Key"+strconv.Itoa(i)+".siakey"), &loadedKeys[i])
if err != nil {
return err
}
}
for _, loadedKey := range loadedKeys {
if loadedKey.UnlockConditions.UnlockHash() != uc.UnlockHash() {
return errors.New("ErrCorruptedKey")
}
}
txn := types.Transaction{
SiafundInputs: []types.SiafundInput{
types.SiafundInput{
UnlockConditions: loadedKeys[0].UnlockConditions,
},
},
}
var i uint64
for i != totalKeys {
if i+keysRequired > totalKeys {
i = totalKeys - keysRequired
}
var j uint64
for j < keysRequired {
txn.TransactionSignatures = append(txn.TransactionSignatures, types.TransactionSignature{
PublicKeyIndex: i,
CoveredFields: types.CoveredFields{WholeTransaction: true},
})
sigHash := txn.SigHash(int(j))
sig, err := crypto.SignHash(sigHash, loadedKeys[i].SecretKey)
if err != nil {
return err
}
txn.TransactionSignatures[j].Signature = sig[:]
i++
j++
}
err := txn.StandaloneValid(0)
if err != nil {
return err
}
txn.TransactionSignatures = nil
}
return nil
}
示例3: 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
}
示例4: BenchmarkStandaloneValid
// BenchmarkStandaloneValid times how long it takes to verify a single
// large transaction, with a certain number of signatures
func BenchmarkStandaloneValid(b *testing.B) {
numSigs := 7
// make a transaction numSigs with valid inputs with valid signatures
b.ReportAllocs()
txn := Transaction{}
sk := make([]crypto.SecretKey, numSigs)
pk := make([]crypto.PublicKey, numSigs)
for i := 0; i < numSigs; i++ {
s, p, err := crypto.GenerateKeyPair()
if err != nil {
b.Fatal(err)
}
sk[i] = s
pk[i] = p
uc := UnlockConditions{
PublicKeys: []SiaPublicKey{
{Algorithm: SignatureEd25519, Key: pk[i][:]},
},
SignaturesRequired: 1,
}
txn.SiacoinInputs = append(txn.SiacoinInputs, SiacoinInput{
UnlockConditions: uc,
})
copy(txn.SiacoinInputs[i].ParentID[:], encoding.Marshal(i))
txn.TransactionSignatures = append(txn.TransactionSignatures, TransactionSignature{
CoveredFields: CoveredFields{WholeTransaction: true},
})
copy(txn.TransactionSignatures[i].ParentID[:], encoding.Marshal(i))
}
// Transaction must be constructed before signing
for i := 0; i < numSigs; i++ {
sigHash := txn.SigHash(i)
sig0, err := crypto.SignHash(sigHash, sk[i])
if err != nil {
b.Fatal(err)
}
txn.TransactionSignatures[i].Signature = sig0[:]
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := txn.StandaloneValid(10)
if err != nil {
b.Fatal(err)
}
}
}
示例5: addSignatures
// addSignatures will sign a transaction using a spendable key, with support
// for multisig spendable keys. Because of the restricted input, the function
// is compatible with both siacoin inputs and siafund inputs.
func addSignatures(txn *types.Transaction, cf types.CoveredFields, uc types.UnlockConditions, parentID crypto.Hash, spendKey spendableKey) (newSigIndices []int, err error) {
// Try to find the matching secret key for each public key - some public
// keys may not have a match. Some secret keys may be used multiple times,
// which is why public keys are used as the outer loop.
totalSignatures := uint64(0)
for i, siaPubKey := range uc.PublicKeys {
// Search for the matching secret key to the public key.
for j := range spendKey.SecretKeys {
pubKey := spendKey.SecretKeys[j].PublicKey()
if bytes.Compare(siaPubKey.Key, pubKey[:]) != 0 {
continue
}
// Found the right secret key, add a signature.
sig := types.TransactionSignature{
ParentID: parentID,
CoveredFields: cf,
PublicKeyIndex: uint64(i),
}
newSigIndices = append(newSigIndices, len(txn.TransactionSignatures))
txn.TransactionSignatures = append(txn.TransactionSignatures, sig)
sigIndex := len(txn.TransactionSignatures) - 1
sigHash := txn.SigHash(sigIndex)
encodedSig, err := crypto.SignHash(sigHash, spendKey.SecretKeys[j])
if err != nil {
return nil, err
}
txn.TransactionSignatures[sigIndex].Signature = encodedSig[:]
// Count that the signature has been added, and break out of the
// secret key loop.
totalSignatures++
break
}
// If there are enough signatures to satisfy the unlock conditions,
// break out of the outer loop.
if totalSignatures == uc.SignaturesRequired {
break
}
}
return newSigIndices, nil
}
示例6: verifyRecentRevision
// verifyRecentRevision confirms that the host and contractor agree upon the current
// state of the contract being revised.
func verifyRecentRevision(conn net.Conn, contract modules.RenterContract) error {
// send contract ID
if err := encoding.WriteObject(conn, contract.ID); err != nil {
return errors.New("couldn't send contract ID: " + err.Error())
}
// read challenge
var challenge crypto.Hash
if err := encoding.ReadObject(conn, &challenge, 32); err != nil {
return errors.New("couldn't read challenge: " + err.Error())
}
// sign and return
sig, err := crypto.SignHash(challenge, contract.SecretKey)
if err != nil {
return err
} else if err := encoding.WriteObject(conn, sig); err != nil {
return errors.New("couldn't send challenge response: " + err.Error())
}
// read acceptance
if err := modules.ReadNegotiationAcceptance(conn); err != nil {
return errors.New("host did not accept revision request: " + err.Error())
}
// read last revision and signatures
var lastRevision types.FileContractRevision
var hostSignatures []types.TransactionSignature
if err := encoding.ReadObject(conn, &lastRevision, 2048); err != nil {
return errors.New("couldn't read last revision: " + err.Error())
}
if err := encoding.ReadObject(conn, &hostSignatures, 2048); err != nil {
return errors.New("couldn't read host signatures: " + err.Error())
}
// Check that the unlock hashes match; if they do not, something is
// seriously wrong. Otherwise, check that the revision numbers match.
if lastRevision.UnlockConditions.UnlockHash() != contract.LastRevision.UnlockConditions.UnlockHash() {
return errors.New("unlock conditions do not match")
} else if lastRevision.NewRevisionNumber != contract.LastRevision.NewRevisionNumber {
return &recentRevisionError{contract.LastRevision.NewRevisionNumber, lastRevision.NewRevisionNumber}
}
// 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).
return modules.VerifyFileContractRevisionTransactionSignatures(lastRevision, hostSignatures, contract.FileContract.WindowStart-1)
}
示例7: CreateAnnouncement
// CreateAnnouncement will take a host announcement and encode it, returning
// the exact []byte that should be added to the arbitrary data of a
// transaction.
func CreateAnnouncement(addr NetAddress, pk types.SiaPublicKey, sk crypto.SecretKey) (signedAnnouncement []byte, err error) {
if err := addr.IsValid(); err != nil {
return nil, err
}
// Create the HostAnnouncement and marshal it.
annBytes := encoding.Marshal(HostAnnouncement{
Specifier: PrefixHostAnnouncement,
NetAddress: addr,
PublicKey: pk,
})
// Create a signature for the announcement.
annHash := crypto.HashBytes(annBytes)
sig, err := crypto.SignHash(annHash, sk)
if err != nil {
return nil, err
}
// Return the signed announcement.
return append(annBytes, sig[:]...), nil
}
示例8: addSignatures
// addSignatures will sign a transaction using a spendable key, with support
// for multisig spendable keys. Because of the restricted input, the function
// is compatible with both siacoin inputs and siafund inputs.
func addSignatures(txn *types.Transaction, cf types.CoveredFields, uc types.UnlockConditions, parentID crypto.Hash, key spendableKey) error {
usedIndices := make(map[int]struct{})
for i := range key.secretKeys {
found := false
keyIndex := 0
pubKey := key.secretKeys[i].PublicKey()
for i, siaPublicKey := range uc.PublicKeys {
_, exists := usedIndices[i]
if !exists && bytes.Compare(pubKey[:], siaPublicKey.Key) == 0 {
found = true
keyIndex = i
break
}
}
if !found && build.DEBUG {
panic("transaction builder cannot sign an input that it added")
}
usedIndices[keyIndex] = struct{}{}
// Create the unsigned transaction signature.
sig := types.TransactionSignature{
ParentID: parentID,
CoveredFields: cf,
PublicKeyIndex: uint64(keyIndex),
}
txn.TransactionSignatures = append(txn.TransactionSignatures, sig)
// Get the signature.
sigIndex := len(txn.TransactionSignatures) - 1
sigHash := txn.SigHash(sigIndex)
encodedSig, err := crypto.SignHash(sigHash, key.secretKeys[i])
if err != nil {
return err
}
txn.TransactionSignatures[sigIndex].Signature = encodedSig[:]
}
return nil
}
示例9: 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
}
示例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: 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
}
示例12: SendSiagSiafunds
//.........這裏部分代碼省略.........
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
}
// Add a refund siafund output if needed.
if amount.Cmp(availableSiafunds) != 0 {
refund := availableSiafunds.Sub(amount)
sfo := types.SiafundOutput{
Value: refund,
UnlockHash: baseUnlockHash,
}
txn, _, err = w.AddSiafundOutput(id, sfo)
if err != nil {
return types.Transaction{}, err
}
}
// Add signatures for the siafund inputs.
sigIndex := 0
for _, sfoid := range sfoids {
for _, key := range skps {
txnSig := types.TransactionSignature{
ParentID: crypto.Hash(sfoid),
CoveredFields: types.CoveredFields{WholeTransaction: true},
PublicKeyIndex: uint64(key.Index),
}
txn.TransactionSignatures = append(txn.TransactionSignatures, txnSig)
sigHash := txn.SigHash(sigIndex)
encodedSig, err := crypto.SignHash(sigHash, key.SecretKey)
if err != nil {
return types.Transaction{}, err
}
txn.TransactionSignatures[sigIndex].Signature = encodedSig[:]
txn, _, err = w.AddTransactionSignature(id, txn.TransactionSignatures[sigIndex])
if err != nil {
return types.Transaction{}, err
}
sigIndex++
}
}
// Sign the transaction.
txn, err = w.SignTransaction(id, true)
if err != nil {
return types.Transaction{}, err
}
err = w.tpool.AcceptTransaction(txn)
if err != nil {
return types.Transaction{}, err
}
return txn, nil
}
示例13: verifyKeys
// verifyKeys checks a set of keys on disk to see that they can spend funds
// sent to their address.
func verifyKeys(uc types.UnlockConditions, folder string, keyname string) error {
keysRequired := uc.SignaturesRequired
totalKeys := uint64(len(uc.PublicKeys))
// Load the keys from disk back into memory, then verify that the keys on
// disk are able to sign outputs in transactions.
loadedKeys := make([]KeyPair, totalKeys)
for i := 0; i < len(loadedKeys); i++ {
err := encoding.ReadFile(filepath.Join(folder, keyname+"_Key"+strconv.Itoa(i)+FileExtension), &loadedKeys[i])
if err != nil {
return err
}
if loadedKeys[i].Header != FileHeader {
return ErrUnknownHeader
}
if loadedKeys[i].Version != FileVersion {
return ErrUnknownVersion
}
}
// Check that the keys can be used to spend transactions.
for _, loadedKey := range loadedKeys {
if loadedKey.UnlockConditions.UnlockHash() != uc.UnlockHash() {
return ErrCorruptedKey
}
}
// Create a transaction for the keys to sign.
txn := types.Transaction{
SiafundInputs: []types.SiafundInput{
types.SiafundInput{
UnlockConditions: loadedKeys[0].UnlockConditions,
},
},
}
// Loop through and sign the transaction multiple times. All keys will be
// used at least once by the time the loop terminates.
var i uint64
for i != totalKeys {
// i tracks which key is next to be used. If i + RequiredKeys results
// in going out-of-bounds, reduce i so that the last key will be used
// for the final signature.
if i+keysRequired > totalKeys {
i = totalKeys - keysRequired
}
var j uint64
for j < keysRequired {
txn.TransactionSignatures = append(txn.TransactionSignatures, types.TransactionSignature{
PublicKeyIndex: i,
CoveredFields: types.CoveredFields{WholeTransaction: true},
})
sigHash := txn.SigHash(int(j))
sig, err := crypto.SignHash(sigHash, loadedKeys[i].SecretKey)
if err != nil {
return err
}
txn.TransactionSignatures[j].Signature = sig[:]
i++
j++
}
// Check that the signature is valid.
err := txn.StandaloneValid(0)
if err != nil {
return err
}
// Delete all of the signatures for the next iteration.
txn.TransactionSignatures = nil
}
return nil
}
示例14: FundTransaction
// FundTransaction adds siacoins to a transaction that the wallet knows how to
// spend. The exact amount of coins are always added, and this is achieved by
// creating two transactions. The first transaciton, the parent, spends a set
// of outputs that add up to at least the desired amount, and then creates a
// single output of the exact amount and a second refund output.
func (w *Wallet) FundTransaction(id string, amount types.Currency) (t types.Transaction, err error) {
counter := w.mu.Lock()
defer w.mu.Unlock(counter)
// Create a parent transaction and supply it with enough inputs to cover
// 'amount'.
parentTxn := types.Transaction{}
fundingOutputs, fundingTotal, err := w.findOutputs(amount)
if err != nil {
return
}
for _, output := range fundingOutputs {
output.age = w.age
key := w.keys[output.output.UnlockHash]
newInput := types.SiacoinInput{
ParentID: output.id,
UnlockConditions: key.unlockConditions,
}
parentTxn.SiacoinInputs = append(parentTxn.SiacoinInputs, newInput)
}
// Create and add the output that will be used to fund the standard
// transaction.
parentDest, parentSpendConds, err := w.coinAddress(false) // false indicates that the address should not be visible to the user
exactOutput := types.SiacoinOutput{
Value: amount,
UnlockHash: parentDest,
}
parentTxn.SiacoinOutputs = append(parentTxn.SiacoinOutputs, exactOutput)
// Create a refund output if needed.
if amount.Cmp(fundingTotal) != 0 {
var refundDest types.UnlockHash
refundDest, _, err = w.coinAddress(false) // false indicates that the address should not be visible to the user
if err != nil {
return
}
refundOutput := types.SiacoinOutput{
Value: fundingTotal.Sub(amount),
UnlockHash: refundDest,
}
parentTxn.SiacoinOutputs = append(parentTxn.SiacoinOutputs, refundOutput)
}
// Sign all of the inputs to the parent trancstion.
coveredFields := types.CoveredFields{WholeTransaction: true}
for _, input := range parentTxn.SiacoinInputs {
sig := types.TransactionSignature{
ParentID: crypto.Hash(input.ParentID),
CoveredFields: coveredFields,
PublicKeyIndex: 0,
}
parentTxn.TransactionSignatures = append(parentTxn.TransactionSignatures, sig)
// Hash the transaction according to the covered fields.
coinAddress := input.UnlockConditions.UnlockHash()
sigIndex := len(parentTxn.TransactionSignatures) - 1
secKey := w.keys[coinAddress].secretKey
sigHash := parentTxn.SigHash(sigIndex)
// Get the signature.
var encodedSig crypto.Signature
encodedSig, err = crypto.SignHash(sigHash, secKey)
if err != nil {
return
}
parentTxn.TransactionSignatures[sigIndex].Signature = types.Signature(encodedSig[:])
}
// Add the exact output to the wallet's knowledgebase before releasing the
// lock, to prevent the wallet from using the exact output elsewhere.
key := w.keys[parentSpendConds.UnlockHash()]
key.outputs[parentTxn.SiacoinOutputID(0)] = &knownOutput{
id: parentTxn.SiacoinOutputID(0),
output: exactOutput,
spendable: true,
age: w.age,
}
// Send the transaction to the transaction pool.
err = w.tpool.AcceptTransaction(parentTxn)
if err != nil {
return
}
// Get the transaction that was originally meant to be funded.
openTxn, exists := w.transactions[id]
if !exists {
err = ErrInvalidID
return
}
txn := openTxn.transaction
// Add the exact output.
//.........這裏部分代碼省略.........
示例15: SignTransaction
// SignTransaction signs the transaction, then deletes the transaction from the
// wallet's internal memory, then returns the transaction.
func (w *Wallet) SignTransaction(id string, wholeTransaction bool) (txn types.Transaction, err error) {
counter := w.mu.Lock()
defer w.mu.Unlock(counter)
// Fetch the transaction.
openTxn, exists := w.transactions[id]
if !exists {
err = ErrInvalidID
return
}
txn = *openTxn.transaction
// Get the coveredfields struct.
var coveredFields types.CoveredFields
if wholeTransaction {
coveredFields = types.CoveredFields{WholeTransaction: true}
} else {
for i := range txn.MinerFees {
coveredFields.MinerFees = append(coveredFields.MinerFees, uint64(i))
}
for i := range txn.SiacoinInputs {
coveredFields.SiacoinInputs = append(coveredFields.SiacoinInputs, uint64(i))
}
for i := range txn.SiacoinOutputs {
coveredFields.SiacoinOutputs = append(coveredFields.SiacoinOutputs, uint64(i))
}
for i := range txn.FileContracts {
coveredFields.FileContracts = append(coveredFields.FileContracts, uint64(i))
}
for i := range txn.StorageProofs {
coveredFields.StorageProofs = append(coveredFields.StorageProofs, uint64(i))
}
for i := range txn.ArbitraryData {
coveredFields.ArbitraryData = append(coveredFields.ArbitraryData, uint64(i))
}
for i := range txn.TransactionSignatures {
coveredFields.TransactionSignatures = append(coveredFields.TransactionSignatures, uint64(i))
}
}
// For each input in the transaction that we added, provide a signature.
for _, inputIndex := range openTxn.inputs {
input := txn.SiacoinInputs[inputIndex]
sig := types.TransactionSignature{
ParentID: crypto.Hash(input.ParentID),
CoveredFields: coveredFields,
PublicKeyIndex: 0,
}
txn.TransactionSignatures = append(txn.TransactionSignatures, sig)
// Hash the transaction according to the covered fields.
coinAddress := input.UnlockConditions.UnlockHash()
sigIndex := len(txn.TransactionSignatures) - 1
secKey := w.keys[coinAddress].secretKey
sigHash := txn.SigHash(sigIndex)
// Get the signature.
var encodedSig crypto.Signature
encodedSig, err = crypto.SignHash(sigHash, secKey)
if err != nil {
return
}
txn.TransactionSignatures[sigIndex].Signature = types.Signature(encodedSig[:])
}
// Delete the open transaction.
delete(w.transactions, id)
return
}