github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/vm/crypto.go (about)

     1  package vm
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"hash"
     6  
     7  	"golang.org/x/crypto/sha3"
     8  
     9  	"github.com/bytom/bytom/crypto"
    10  	"github.com/bytom/bytom/crypto/ed25519"
    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  	cost := int64(len(x))
    28  	if cost < 64 {
    29  		cost = 64
    30  	}
    31  	err = vm.applyCost(cost)
    32  	if err != nil {
    33  		return err
    34  	}
    35  	h := hashFactory()
    36  	_, err = h.Write(x)
    37  	if err != nil {
    38  		return err
    39  	}
    40  	return vm.push(h.Sum(nil), false)
    41  }
    42  
    43  func opCheckSig(vm *virtualMachine) error {
    44  	err := vm.applyCost(1024)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	pubkeyBytes, err := vm.pop(true)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	msg, err := vm.pop(true)
    53  	if err != nil {
    54  		return err
    55  	}
    56  	sig, err := vm.pop(true)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	if len(msg) != 32 {
    61  		return ErrBadValue
    62  	}
    63  	if len(pubkeyBytes) != ed25519.PublicKeySize {
    64  		return vm.pushBool(false, true)
    65  	}
    66  	return vm.pushBool(ed25519.Verify(ed25519.PublicKey(pubkeyBytes), msg, sig), true)
    67  }
    68  
    69  func opCheckMultiSig(vm *virtualMachine) error {
    70  	numPubkeys, err := vm.popInt64(true)
    71  	if err != nil {
    72  		return err
    73  	}
    74  	pubCost, ok := checked.MulInt64(numPubkeys, 1024)
    75  	if numPubkeys < 0 || !ok {
    76  		return ErrBadValue
    77  	}
    78  	err = vm.applyCost(pubCost)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	numSigs, err := vm.popInt64(true)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	if numSigs < 0 || numSigs > numPubkeys || (numPubkeys > 0 && numSigs == 0) {
    87  		return ErrBadValue
    88  	}
    89  	pubkeyByteses := make([][]byte, 0, numPubkeys)
    90  	for i := int64(0); i < numPubkeys; i++ {
    91  		pubkeyBytes, err := vm.pop(true)
    92  		if err != nil {
    93  			return err
    94  		}
    95  		pubkeyByteses = append(pubkeyByteses, pubkeyBytes)
    96  	}
    97  	msg, err := vm.pop(true)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	if len(msg) != 32 {
   102  		return ErrBadValue
   103  	}
   104  	sigs := make([][]byte, 0, numSigs)
   105  	for i := int64(0); i < numSigs; i++ {
   106  		sig, err := vm.pop(true)
   107  		if err != nil {
   108  			return err
   109  		}
   110  		sigs = append(sigs, sig)
   111  	}
   112  
   113  	pubkeys := make([]ed25519.PublicKey, 0, numPubkeys)
   114  	for _, p := range pubkeyByteses {
   115  		if len(p) != ed25519.PublicKeySize {
   116  			return vm.pushBool(false, true)
   117  		}
   118  		pubkeys = append(pubkeys, ed25519.PublicKey(p))
   119  	}
   120  
   121  	for len(sigs) > 0 && len(pubkeys) > 0 {
   122  		if ed25519.Verify(pubkeys[0], msg, sigs[0]) {
   123  			sigs = sigs[1:]
   124  		}
   125  		pubkeys = pubkeys[1:]
   126  	}
   127  	return vm.pushBool(len(sigs) == 0, true)
   128  }
   129  
   130  func opTxSigHash(vm *virtualMachine) error {
   131  	err := vm.applyCost(256)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	if vm.context.TxSigHash == nil {
   136  		return ErrContext
   137  	}
   138  	return vm.push(vm.context.TxSigHash(), false)
   139  }
   140  
   141  func opHash160(vm *virtualMachine) error {
   142  	data, err := vm.pop(false)
   143  	if err != nil {
   144  		return err
   145  	}
   146  
   147  	cost := int64(len(data) + 64)
   148  	if err = vm.applyCost(cost); err != nil {
   149  		return err
   150  	}
   151  
   152  	return vm.push(crypto.Ripemd160(data), false)
   153  }