github.com/Synthesix/Sia@v1.3.3-0.20180413141344-f863baeed3ca/types/signatures.go (about)

     1  package types
     2  
     3  // signatures.go contains all of the types and functions related to creating
     4  // and verifying transaction signatures. There are a lot of rules surrounding
     5  // the correct use of signatures. Signatures can cover part or all of a
     6  // transaction, can be multiple different algorithms, and must satify a field
     7  // called 'UnlockConditions'.
     8  
     9  import (
    10  	"bytes"
    11  	"errors"
    12  
    13  	"github.com/Synthesix/Sia/crypto"
    14  	"github.com/Synthesix/Sia/encoding"
    15  )
    16  
    17  var (
    18  	// ErrEntropyKey is the error when a transaction tries to sign an entropy
    19  	// public key
    20  	ErrEntropyKey = errors.New("transaction tries to sign an entropy public key")
    21  	// ErrFrivolousSignature is the error when a transaction contains a frivolous
    22  	// signature
    23  	ErrFrivolousSignature = errors.New("transaction contains a frivolous signature")
    24  	// ErrInvalidPubKeyIndex is the error when a transaction contains a signature
    25  	// that points to a nonexistent public key
    26  	ErrInvalidPubKeyIndex = errors.New("transaction contains a signature that points to a nonexistent public key")
    27  	// ErrInvalidUnlockHashChecksum is the error when the provided unlock hash has
    28  	// an invalid checksum
    29  	ErrInvalidUnlockHashChecksum = errors.New("provided unlock hash has an invalid checksum")
    30  	// ErrMissingSignatures is the error when a transaction has inputs with missing
    31  	// signatures
    32  	ErrMissingSignatures = errors.New("transaction has inputs with missing signatures")
    33  	// ErrPrematureSignature is the error when the timelock on signature has not
    34  	// expired
    35  	ErrPrematureSignature = errors.New("timelock on signature has not expired")
    36  	// ErrPublicKeyOveruse is the error when public key was used multiple times while
    37  	// signing transaction
    38  	ErrPublicKeyOveruse = errors.New("public key was used multiple times while signing transaction")
    39  	// ErrSortedUniqueViolation is the error when a sorted unique violation occurs
    40  	ErrSortedUniqueViolation = errors.New("sorted unique violation")
    41  	// ErrUnlockHashWrongLen is the error when a marshalled unlock hash is the wrong
    42  	// length
    43  	ErrUnlockHashWrongLen = errors.New("marshalled unlock hash is the wrong length")
    44  	// ErrWholeTransactionViolation is the error when there's a covered fields violation
    45  	ErrWholeTransactionViolation = errors.New("covered fields violation")
    46  
    47  	// FullCoveredFields is a covered fileds object where the
    48  	// 'WholeTransaction' field has been set to true. The primary purpose of
    49  	// this variable is syntactic sugar.
    50  	FullCoveredFields = CoveredFields{WholeTransaction: true}
    51  
    52  	// These Specifiers enumerate the types of signatures that are recognized
    53  	// by this implementation. If a signature's type is unrecognized, the
    54  	// signature is treated as valid. Signatures using the special "entropy"
    55  	// type are always treated as invalid; see Consensus.md for more details.
    56  
    57  	// SignatureEd25519 is a specifier for Ed22519
    58  	SignatureEd25519 = Specifier{'e', 'd', '2', '5', '5', '1', '9'}
    59  	// SignatureEntropy is a specifier for entropy
    60  	SignatureEntropy = Specifier{'e', 'n', 't', 'r', 'o', 'p', 'y'}
    61  )
    62  
    63  type (
    64  	// CoveredFields indicates which fields in a transaction have been covered by
    65  	// the signature. (Note that the signature does not sign the fields
    66  	// themselves, but rather their combined hash; see SigHash.) Each slice
    67  	// corresponds to a slice in the Transaction type, indicating which indices of
    68  	// the slice have been signed. The indices must be valid, i.e. within the
    69  	// bounds of the slice. In addition, they must be sorted and unique.
    70  	//
    71  	// As a convenience, a signature of the entire transaction can be indicated by
    72  	// the 'WholeTransaction' field. If 'WholeTransaction' == true, all other
    73  	// fields must be empty (except for the Signatures field, since a signature
    74  	// cannot sign itself).
    75  	CoveredFields struct {
    76  		WholeTransaction      bool     `json:"wholetransaction"`
    77  		SiacoinInputs         []uint64 `json:"siacoininputs"`
    78  		SiacoinOutputs        []uint64 `json:"siacoinoutputs"`
    79  		FileContracts         []uint64 `json:"filecontracts"`
    80  		FileContractRevisions []uint64 `json:"filecontractrevisions"`
    81  		StorageProofs         []uint64 `json:"storageproofs"`
    82  		SiafundInputs         []uint64 `json:"siafundinputs"`
    83  		SiafundOutputs        []uint64 `json:"siafundoutputs"`
    84  		MinerFees             []uint64 `json:"minerfees"`
    85  		ArbitraryData         []uint64 `json:"arbitrarydata"`
    86  		TransactionSignatures []uint64 `json:"transactionsignatures"`
    87  	}
    88  
    89  	// A SiaPublicKey is a public key prefixed by a Specifier. The Specifier
    90  	// indicates the algorithm used for signing and verification. Unrecognized
    91  	// algorithms will always verify, which allows new algorithms to be added to
    92  	// the protocol via a soft-fork.
    93  	SiaPublicKey struct {
    94  		Algorithm Specifier `json:"algorithm"`
    95  		Key       []byte    `json:"key"`
    96  	}
    97  
    98  	// A TransactionSignature is a signature that is included in the transaction.
    99  	// The signature should correspond to a public key in one of the
   100  	// UnlockConditions of the transaction. This key is specified first by
   101  	// 'ParentID', which specifies the UnlockConditions, and then
   102  	// 'PublicKeyIndex', which indicates the key in the UnlockConditions. There
   103  	// are three types that use UnlockConditions: SiacoinInputs, SiafundInputs,
   104  	// and FileContractTerminations. Each of these types also references a
   105  	// ParentID, and this is the hash that 'ParentID' must match. The 'Timelock'
   106  	// prevents the signature from being used until a certain height.
   107  	// 'CoveredFields' indicates which parts of the transaction are being signed;
   108  	// see CoveredFields.
   109  	TransactionSignature struct {
   110  		ParentID       crypto.Hash   `json:"parentid"`
   111  		PublicKeyIndex uint64        `json:"publickeyindex"`
   112  		Timelock       BlockHeight   `json:"timelock"`
   113  		CoveredFields  CoveredFields `json:"coveredfields"`
   114  		Signature      []byte        `json:"signature"`
   115  	}
   116  
   117  	// UnlockConditions are a set of conditions which must be met to execute
   118  	// certain actions, such as spending a SiacoinOutput or terminating a
   119  	// FileContract.
   120  	//
   121  	// The simplest requirement is that the block containing the UnlockConditions
   122  	// must have a height >= 'Timelock'.
   123  	//
   124  	// 'PublicKeys' specifies the set of keys that can be used to satisfy the
   125  	// UnlockConditions; of these, at least 'SignaturesRequired' unique keys must sign
   126  	// the transaction. The keys that do not need to use the same cryptographic
   127  	// algorithm.
   128  	//
   129  	// If 'SignaturesRequired' == 0, the UnlockConditions are effectively "anyone can
   130  	// unlock." If 'SignaturesRequired' > len('PublicKeys'), then the UnlockConditions
   131  	// cannot be fulfilled under any circumstances.
   132  	UnlockConditions struct {
   133  		Timelock           BlockHeight    `json:"timelock"`
   134  		PublicKeys         []SiaPublicKey `json:"publickeys"`
   135  		SignaturesRequired uint64         `json:"signaturesrequired"`
   136  	}
   137  
   138  	// Each input has a list of public keys and a required number of signatures.
   139  	// inputSignatures keeps track of which public keys have been used and how many
   140  	// more signatures are needed.
   141  	inputSignatures struct {
   142  		remainingSignatures uint64
   143  		possibleKeys        []SiaPublicKey
   144  		usedKeys            map[uint64]struct{}
   145  		index               int
   146  	}
   147  )
   148  
   149  // Ed25519PublicKey returns pk as a SiaPublicKey, denoting its algorithm as
   150  // Ed25519.
   151  func Ed25519PublicKey(pk crypto.PublicKey) SiaPublicKey {
   152  	return SiaPublicKey{
   153  		Algorithm: SignatureEd25519,
   154  		Key:       pk[:],
   155  	}
   156  }
   157  
   158  // UnlockHash calculates the root hash of a Merkle tree of the
   159  // UnlockConditions object. The leaves of this tree are formed by taking the
   160  // hash of the timelock, the hash of the public keys (one leaf each), and the
   161  // hash of the number of signatures. The keys are put in the middle because
   162  // Timelock and SignaturesRequired are both low entropy fields; they can be
   163  // protected by having random public keys next to them.
   164  func (uc UnlockConditions) UnlockHash() UnlockHash {
   165  	var buf bytes.Buffer
   166  	e := encoder(&buf)
   167  	tree := crypto.NewTree()
   168  	e.WriteUint64(uint64(uc.Timelock))
   169  	tree.Push(buf.Bytes())
   170  	buf.Reset()
   171  	for _, key := range uc.PublicKeys {
   172  		key.MarshalSia(e)
   173  		tree.Push(buf.Bytes())
   174  		buf.Reset()
   175  	}
   176  	e.WriteUint64(uc.SignaturesRequired)
   177  	tree.Push(buf.Bytes())
   178  	return UnlockHash(tree.Root())
   179  }
   180  
   181  // SigHash returns the hash of the fields in a transaction covered by a given
   182  // signature. See CoveredFields for more details.
   183  func (t Transaction) SigHash(i int) (hash crypto.Hash) {
   184  	cf := t.TransactionSignatures[i].CoveredFields
   185  	h := crypto.NewHash()
   186  	if cf.WholeTransaction {
   187  		t.marshalSiaNoSignatures(h)
   188  		h.Write(t.TransactionSignatures[i].ParentID[:])
   189  		encoding.WriteUint64(h, t.TransactionSignatures[i].PublicKeyIndex)
   190  		encoding.WriteUint64(h, uint64(t.TransactionSignatures[i].Timelock))
   191  	} else {
   192  		for _, input := range cf.SiacoinInputs {
   193  			t.SiacoinInputs[input].MarshalSia(h)
   194  		}
   195  		for _, output := range cf.SiacoinOutputs {
   196  			t.SiacoinOutputs[output].MarshalSia(h)
   197  		}
   198  		for _, contract := range cf.FileContracts {
   199  			t.FileContracts[contract].MarshalSia(h)
   200  		}
   201  		for _, revision := range cf.FileContractRevisions {
   202  			t.FileContractRevisions[revision].MarshalSia(h)
   203  		}
   204  		for _, storageProof := range cf.StorageProofs {
   205  			t.StorageProofs[storageProof].MarshalSia(h)
   206  		}
   207  		for _, siafundInput := range cf.SiafundInputs {
   208  			t.SiafundInputs[siafundInput].MarshalSia(h)
   209  		}
   210  		for _, siafundOutput := range cf.SiafundOutputs {
   211  			t.SiafundOutputs[siafundOutput].MarshalSia(h)
   212  		}
   213  		for _, minerFee := range cf.MinerFees {
   214  			t.MinerFees[minerFee].MarshalSia(h)
   215  		}
   216  		for _, arbData := range cf.ArbitraryData {
   217  			encoding.WritePrefix(h, t.ArbitraryData[arbData])
   218  		}
   219  	}
   220  
   221  	for _, sig := range cf.TransactionSignatures {
   222  		t.TransactionSignatures[sig].MarshalSia(h)
   223  	}
   224  
   225  	h.Sum(hash[:0])
   226  	return
   227  }
   228  
   229  // sortedUnique checks that 'elems' is sorted, contains no repeats, and that no
   230  // element is larger than or equal to 'max'.
   231  func sortedUnique(elems []uint64, max int) bool {
   232  	if len(elems) == 0 {
   233  		return true
   234  	}
   235  
   236  	biggest := elems[0]
   237  	for _, elem := range elems[1:] {
   238  		if elem <= biggest {
   239  			return false
   240  		}
   241  		biggest = elem
   242  	}
   243  	if biggest >= uint64(max) {
   244  		return false
   245  	}
   246  	return true
   247  }
   248  
   249  // validCoveredFields makes sure that all covered fields objects in the
   250  // signatures follow the rules. This means that if 'WholeTransaction' is set to
   251  // true, all fields except for 'Signatures' must be empty. All fields must be
   252  // sorted numerically, and there can be no repeats.
   253  func (t Transaction) validCoveredFields() error {
   254  	for _, sig := range t.TransactionSignatures {
   255  		// convenience variables
   256  		cf := sig.CoveredFields
   257  		fieldMaxs := []struct {
   258  			field []uint64
   259  			max   int
   260  		}{
   261  			{cf.SiacoinInputs, len(t.SiacoinInputs)},
   262  			{cf.SiacoinOutputs, len(t.SiacoinOutputs)},
   263  			{cf.FileContracts, len(t.FileContracts)},
   264  			{cf.FileContractRevisions, len(t.FileContractRevisions)},
   265  			{cf.StorageProofs, len(t.StorageProofs)},
   266  			{cf.SiafundInputs, len(t.SiafundInputs)},
   267  			{cf.SiafundOutputs, len(t.SiafundOutputs)},
   268  			{cf.MinerFees, len(t.MinerFees)},
   269  			{cf.ArbitraryData, len(t.ArbitraryData)},
   270  			{cf.TransactionSignatures, len(t.TransactionSignatures)},
   271  		}
   272  
   273  		// Check that all fields are empty if 'WholeTransaction' is set, except
   274  		// for the Signatures field which isn't affected.
   275  		if cf.WholeTransaction {
   276  			// 'WholeTransaction' does not check signatures.
   277  			for _, fieldMax := range fieldMaxs[:len(fieldMaxs)-1] {
   278  				if len(fieldMax.field) != 0 {
   279  					return ErrWholeTransactionViolation
   280  				}
   281  			}
   282  		}
   283  
   284  		// Check that all fields are sorted, and without repeat values, and
   285  		// that all elements point to objects that exists within the
   286  		// transaction. If there are repeats, it means a transaction is trying
   287  		// to sign the same object twice. This is unncecessary, and opens up a
   288  		// DoS vector where the transaction asks the verifier to verify many GB
   289  		// of data.
   290  		for _, fieldMax := range fieldMaxs {
   291  			if !sortedUnique(fieldMax.field, fieldMax.max) {
   292  				return ErrSortedUniqueViolation
   293  			}
   294  		}
   295  	}
   296  
   297  	return nil
   298  }
   299  
   300  // validSignatures checks the validaty of all signatures in a transaction.
   301  func (t *Transaction) validSignatures(currentHeight BlockHeight) error {
   302  	// Check that all covered fields objects follow the rules.
   303  	err := t.validCoveredFields()
   304  	if err != nil {
   305  		return err
   306  	}
   307  
   308  	// Create the inputSignatures object for each input.
   309  	sigMap := make(map[crypto.Hash]*inputSignatures)
   310  	for i, input := range t.SiacoinInputs {
   311  		id := crypto.Hash(input.ParentID)
   312  		_, exists := sigMap[id]
   313  		if exists {
   314  			return ErrDoubleSpend
   315  		}
   316  
   317  		sigMap[id] = &inputSignatures{
   318  			remainingSignatures: input.UnlockConditions.SignaturesRequired,
   319  			possibleKeys:        input.UnlockConditions.PublicKeys,
   320  			usedKeys:            make(map[uint64]struct{}),
   321  			index:               i,
   322  		}
   323  	}
   324  	for i, revision := range t.FileContractRevisions {
   325  		id := crypto.Hash(revision.ParentID)
   326  		_, exists := sigMap[id]
   327  		if exists {
   328  			return ErrDoubleSpend
   329  		}
   330  
   331  		sigMap[id] = &inputSignatures{
   332  			remainingSignatures: revision.UnlockConditions.SignaturesRequired,
   333  			possibleKeys:        revision.UnlockConditions.PublicKeys,
   334  			usedKeys:            make(map[uint64]struct{}),
   335  			index:               i,
   336  		}
   337  	}
   338  	for i, input := range t.SiafundInputs {
   339  		id := crypto.Hash(input.ParentID)
   340  		_, exists := sigMap[id]
   341  		if exists {
   342  			return ErrDoubleSpend
   343  		}
   344  
   345  		sigMap[id] = &inputSignatures{
   346  			remainingSignatures: input.UnlockConditions.SignaturesRequired,
   347  			possibleKeys:        input.UnlockConditions.PublicKeys,
   348  			usedKeys:            make(map[uint64]struct{}),
   349  			index:               i,
   350  		}
   351  	}
   352  
   353  	// Check all of the signatures for validity.
   354  	for i, sig := range t.TransactionSignatures {
   355  		// Check that sig corresponds to an entry in sigMap.
   356  		inSig, exists := sigMap[crypto.Hash(sig.ParentID)]
   357  		if !exists || inSig.remainingSignatures == 0 {
   358  			return ErrFrivolousSignature
   359  		}
   360  		// Check that sig's key hasn't already been used.
   361  		_, exists = inSig.usedKeys[sig.PublicKeyIndex]
   362  		if exists {
   363  			return ErrPublicKeyOveruse
   364  		}
   365  		// Check that the public key index refers to an existing public key.
   366  		if sig.PublicKeyIndex >= uint64(len(inSig.possibleKeys)) {
   367  			return ErrInvalidPubKeyIndex
   368  		}
   369  		// Check that the timelock has expired.
   370  		if sig.Timelock > currentHeight {
   371  			return ErrPrematureSignature
   372  		}
   373  
   374  		// Check that the signature verifies. Multiple signature schemes are
   375  		// supported.
   376  		publicKey := inSig.possibleKeys[sig.PublicKeyIndex]
   377  		switch publicKey.Algorithm {
   378  		case SignatureEntropy:
   379  			// Entropy cannot ever be used to sign a transaction.
   380  			return ErrEntropyKey
   381  
   382  		case SignatureEd25519:
   383  			// Decode the public key and signature.
   384  			var edPK crypto.PublicKey
   385  			err := encoding.Unmarshal([]byte(publicKey.Key), &edPK)
   386  			if err != nil {
   387  				return err
   388  			}
   389  			var edSig [crypto.SignatureSize]byte
   390  			err = encoding.Unmarshal([]byte(sig.Signature), &edSig)
   391  			if err != nil {
   392  				return err
   393  			}
   394  			cryptoSig := crypto.Signature(edSig)
   395  
   396  			sigHash := t.SigHash(i)
   397  			err = crypto.VerifyHash(sigHash, edPK, cryptoSig)
   398  			if err != nil {
   399  				return err
   400  			}
   401  
   402  		default:
   403  			// If the identifier is not recognized, assume that the signature
   404  			// is valid. This allows more signature types to be added via soft
   405  			// forking.
   406  		}
   407  
   408  		inSig.usedKeys[sig.PublicKeyIndex] = struct{}{}
   409  		inSig.remainingSignatures--
   410  	}
   411  
   412  	// Check that all inputs have been sufficiently signed.
   413  	for _, reqSigs := range sigMap {
   414  		if reqSigs.remainingSignatures != 0 {
   415  			return ErrMissingSignatures
   416  		}
   417  	}
   418  
   419  	return nil
   420  }