Beispiel #1
0
// LoadString loads a hex representation (including checksum) of an unlock hash
// into an unlock hash object. An error is returned if the string is invalid or
// fails the checksum.
func (uh *UnlockHash) LoadString(strUH string) error {
	// Check the length of strUH.
	if len(strUH) != crypto.HashSize*2+UnlockHashChecksumSize*2 {
		return ErrUnlockHashWrongLen
	}

	// Decode the unlock hash.
	var byteUnlockHash []byte
	var checksum []byte
	_, err := fmt.Sscanf(strUH[:crypto.HashSize*2], "%x", &byteUnlockHash)
	if err != nil {
		return err
	}

	// Decode and verify the checksum.
	_, err = fmt.Sscanf(strUH[crypto.HashSize*2:], "%x", &checksum)
	if err != nil {
		return err
	}
	expectedChecksum := crypto.HashBytes(byteUnlockHash)
	if !bytes.Equal(expectedChecksum[:UnlockHashChecksumSize], checksum) {
		return ErrInvalidUnlockHashChecksum
	}

	copy(uh[:], byteUnlockHash[:])
	return nil
}
Beispiel #2
0
// LoadString loads a hex representation (including checksum) of an unlock hash
// into an unlock hash object. An error is returned if the string is invalid or
// fails the checksum.
func (uh *UnlockHash) LoadString(strUH string) error {
	// Check the length of strUH.
	if len(strUH) != crypto.HashSize*2+UnlockHashChecksumSize*2 && len(strUH) != crypto.HashSize*2 {
		return ErrUnlockHashWrongLen
	}

	// Decode the unlock hash.
	var byteUnlockHash []byte
	var checksum []byte
	_, err := fmt.Sscanf(strUH[:crypto.HashSize*2], "%x", &byteUnlockHash)
	if err != nil {
		return err
	}
	// Decode the checksum, if provided.
	if len(strUH) == crypto.HashSize*2+UnlockHashChecksumSize*2 {
		_, err = fmt.Sscanf(strUH[crypto.HashSize*2:], "%x", &checksum)
		if err != nil {
			return err
		}

		// Verify the checksum - leave uh as-is unless the checksum is valid.
		expectedChecksum := crypto.HashBytes(byteUnlockHash)
		if bytes.Compare(expectedChecksum[:UnlockHashChecksumSize], checksum) != 0 {
			return ErrInvalidUnlockHashChecksum
		}
	}
	copy(uh[:], byteUnlockHash[:])

	return nil
}
Beispiel #3
0
// SigHash returns the hash of the fields in a transaction covered by a given
// signature. See CoveredFields for more details.
func (t Transaction) SigHash(i int) crypto.Hash {
	cf := t.TransactionSignatures[i].CoveredFields
	var signedData []byte
	if cf.WholeTransaction {
		signedData = encoding.MarshalAll(
			t.SiacoinInputs,
			t.SiacoinOutputs,
			t.FileContracts,
			t.FileContractRevisions,
			t.StorageProofs,
			t.SiafundInputs,
			t.SiafundOutputs,
			t.MinerFees,
			t.ArbitraryData,
			t.TransactionSignatures[i].ParentID,
			t.TransactionSignatures[i].PublicKeyIndex,
			t.TransactionSignatures[i].Timelock,
		)
	} else {
		for _, input := range cf.SiacoinInputs {
			signedData = append(signedData, encoding.Marshal(t.SiacoinInputs[input])...)
		}
		for _, output := range cf.SiacoinOutputs {
			signedData = append(signedData, encoding.Marshal(t.SiacoinOutputs[output])...)
		}
		for _, contract := range cf.FileContracts {
			signedData = append(signedData, encoding.Marshal(t.FileContracts[contract])...)
		}
		for _, revision := range cf.FileContractRevisions {
			signedData = append(signedData, encoding.Marshal(t.FileContractRevisions[revision])...)
		}
		for _, storageProof := range cf.StorageProofs {
			signedData = append(signedData, encoding.Marshal(t.StorageProofs[storageProof])...)
		}
		for _, siafundInput := range cf.SiafundInputs {
			signedData = append(signedData, encoding.Marshal(t.SiafundInputs[siafundInput])...)
		}
		for _, siafundOutput := range cf.SiafundOutputs {
			signedData = append(signedData, encoding.Marshal(t.SiafundOutputs[siafundOutput])...)
		}
		for _, minerFee := range cf.MinerFees {
			signedData = append(signedData, encoding.Marshal(t.MinerFees[minerFee])...)
		}
		for _, arbData := range cf.ArbitraryData {
			signedData = append(signedData, encoding.Marshal(t.ArbitraryData[arbData])...)
		}
	}

	for _, sig := range cf.TransactionSignatures {
		signedData = append(signedData, encoding.Marshal(t.TransactionSignatures[sig])...)
	}

	return crypto.HashBytes(signedData)
}
Beispiel #4
0
// SolveBlock takes a block, target, and number of iterations as input and
// tries to find a block that meets the target. This function can take a long
// time to complete, and should not be called with a lock.
func (m *Miner) SolveBlock(b types.Block, target types.Target) (types.Block, bool) {
	// Assemble the header.
	merkleRoot := b.MerkleRoot()
	header := make([]byte, 80)
	copy(header, b.ParentID[:])
	binary.LittleEndian.PutUint64(header[40:48], uint64(b.Timestamp))
	copy(header[48:], merkleRoot[:])

	nonce := (*uint64)(unsafe.Pointer(&header[32]))
	for i := 0; i < iterationsPerAttempt; i++ {
		id := crypto.HashBytes(header)
		if bytes.Compare(target[:], id[:]) >= 0 {
			copy(b.Nonce[:], header[32:40])
			return b, true
		}
		*nonce++
	}
	return b, false
}
Beispiel #5
0
// TestBlockHeader checks that BlockHeader returns the correct value, and that
// the hash is consistent with the old method for obtaining the hash.
func TestBlockHeader(t *testing.T) {
	var b Block
	b.ParentID[1] = 1
	b.Nonce[2] = 2
	b.Timestamp = 3
	b.MinerPayouts = []SiacoinOutput{{Value: NewCurrency64(4)}}
	b.Transactions = []Transaction{{ArbitraryData: [][]byte{[]byte{'5'}}}}

	id1 := b.ID()
	id2 := BlockID(crypto.HashBytes(encoding.Marshal(b.Header())))
	id3 := BlockID(crypto.HashAll(
		b.ParentID,
		b.Nonce,
		b.Timestamp,
		b.MerkleRoot(),
	))

	if id1 != id2 || id2 != id3 || id3 != id1 {
		t.Error("Methods for getting block id don't return the same results")
	}
}
Beispiel #6
0
// 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
}