github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/vm/crypto.go (about)

     1  package vm
     2  
     3  import (
     4  	"crypto/ed25519"
     5  	"crypto/sha256"
     6  	"hash"
     7  
     8  	"golang.org/x/crypto/sha3"
     9  
    10  	"github.com/bytom/bytom/crypto"
    11  	"github.com/bytom/bytom/math/checked"
    12  )
    13  
    14  func opSha256(vm *virtualMachine) error {
    15  	return doHash(vm, sha256.New)
    16  }
    17  
    18  func opSha3(vm *virtualMachine) error {
    19  	return doHash(vm, sha3.New256)
    20  }
    21  
    22  func doHash(vm *virtualMachine, hashFactory func() hash.Hash) error {
    23  	x, err := vm.pop(false)
    24  	if err != nil {
    25  		return err
    26  	}
    27  
    28  	cost := int64(len(x))
    29  	if cost < 64 {
    30  		cost = 64
    31  	}
    32  
    33  	if err = vm.applyCost(cost); err != nil {
    34  		return err
    35  	}
    36  
    37  	h := hashFactory()
    38  	if _, err = h.Write(x); err != nil {
    39  		return err
    40  	}
    41  	return vm.pushDataStack(h.Sum(nil), false)
    42  }
    43  
    44  func opCheckSig(vm *virtualMachine) error {
    45  	if err := vm.applyCost(1024); err != nil {
    46  		return err
    47  	}
    48  
    49  	pubkeyBytes, err := vm.pop(true)
    50  	if err != nil {
    51  		return err
    52  	}
    53  
    54  	msg, err := vm.pop(true)
    55  	if err != nil {
    56  		return err
    57  	}
    58  
    59  	sig, err := vm.pop(true)
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	if len(msg) != 32 {
    65  		return ErrBadValue
    66  	}
    67  
    68  	if len(pubkeyBytes) != ed25519.PublicKeySize {
    69  		return vm.pushBool(false, true)
    70  	}
    71  	return vm.pushBool(ed25519.Verify(ed25519.PublicKey(pubkeyBytes), msg, sig), true)
    72  }
    73  
    74  func opCheckMultiSig(vm *virtualMachine) error {
    75  	numPubkeysBigInt, err := vm.popBigInt(true)
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	numPubkeys, err := bigIntInt64(numPubkeysBigInt)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	pubCost, ok := checked.MulInt64(numPubkeys, 1024)
    86  	if numPubkeys < 0 || !ok {
    87  		return ErrBadValue
    88  	}
    89  
    90  	if err = vm.applyCost(pubCost); err != nil {
    91  		return err
    92  	}
    93  
    94  	numSigsBigInt, err := vm.popBigInt(true)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	numSigs, err := bigIntInt64(numSigsBigInt)
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	if numSigs < 0 || numSigs > numPubkeys || (numPubkeys > 0 && numSigs == 0) {
   105  		return ErrBadValue
   106  	}
   107  
   108  	pubkeyByteses := make([][]byte, 0, numPubkeys)
   109  	for i := int64(0); i < numPubkeys; i++ {
   110  		pubkeyBytes, err := vm.pop(true)
   111  		if err != nil {
   112  			return err
   113  		}
   114  		pubkeyByteses = append(pubkeyByteses, pubkeyBytes)
   115  	}
   116  
   117  	msg, err := vm.pop(true)
   118  	if err != nil {
   119  		return err
   120  	}
   121  
   122  	if len(msg) != 32 {
   123  		return ErrBadValue
   124  	}
   125  
   126  	sigs := make([][]byte, 0, numSigs)
   127  	for i := int64(0); i < numSigs; i++ {
   128  		sig, err := vm.pop(true)
   129  		if err != nil {
   130  			return err
   131  		}
   132  		sigs = append(sigs, sig)
   133  	}
   134  
   135  	pubkeys := make([]ed25519.PublicKey, 0, numPubkeys)
   136  	for _, p := range pubkeyByteses {
   137  		if len(p) != ed25519.PublicKeySize {
   138  			return vm.pushBool(false, true)
   139  		}
   140  		pubkeys = append(pubkeys, ed25519.PublicKey(p))
   141  	}
   142  
   143  	for len(sigs) > 0 && len(pubkeys) > 0 {
   144  		if ed25519.Verify(pubkeys[0], msg, sigs[0]) {
   145  			sigs = sigs[1:]
   146  		}
   147  		pubkeys = pubkeys[1:]
   148  	}
   149  
   150  	return vm.pushBool(len(sigs) == 0, true)
   151  }
   152  
   153  func opTxSigHash(vm *virtualMachine) error {
   154  	if err := vm.applyCost(256); err != nil {
   155  		return err
   156  	}
   157  
   158  	if vm.context.TxSigHash == nil {
   159  		return ErrContext
   160  	}
   161  
   162  	return vm.pushDataStack(vm.context.TxSigHash(), false)
   163  }
   164  
   165  func opHash160(vm *virtualMachine) error {
   166  	data, err := vm.pop(false)
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	cost := int64(len(data) + 64)
   172  	if err = vm.applyCost(cost); err != nil {
   173  		return err
   174  	}
   175  
   176  	return vm.pushDataStack(crypto.Ripemd160(data), false)
   177  }