| 95 | } |
| 96 | |
| 97 | func ParseP2SPMultiSigProgram(program []byte) ([]ed25519.PublicKey, int, error) { |
| 98 | pops, err := vm.ParseProgram(program) |
| 99 | if err != nil { |
| 100 | return nil, 0, err |
| 101 | } |
| 102 | if len(pops) < 11 { |
| 103 | return nil, 0, vm.ErrShortProgram |
| 104 | } |
| 105 | |
| 106 | // Count all instructions backwards from the end in case there are |
| 107 | // extra instructions at the beginning of the program (like a |
| 108 | // <pushdata> DROP). |
| 109 | |
| 110 | npubkeys, err := vm.AsInt64(pops[len(pops)-6].Data) |
| 111 | if err != nil { |
| 112 | return nil, 0, err |
| 113 | } |
| 114 | if int(npubkeys) > len(pops)-10 { |
| 115 | return nil, 0, vm.ErrShortProgram |
| 116 | } |
| 117 | nrequired, err := vm.AsInt64(pops[len(pops)-7].Data) |
| 118 | if err != nil { |
| 119 | return nil, 0, err |
| 120 | } |
| 121 | err = checkMultiSigParams(nrequired, npubkeys) |
| 122 | if err != nil { |
| 123 | return nil, 0, err |
| 124 | } |
| 125 | |
| 126 | firstPubkeyIndex := len(pops) - 7 - int(npubkeys) |
| 127 | |
| 128 | pubkeys := make([]ed25519.PublicKey, 0, npubkeys) |
| 129 | for i := firstPubkeyIndex; i < firstPubkeyIndex+int(npubkeys); i++ { |
| 130 | if len(pops[i].Data) != ed25519.PublicKeySize { |
| 131 | return nil, 0, err |
| 132 | } |
| 133 | pubkeys = append(pubkeys, ed25519.PublicKey(pops[i].Data)) |
| 134 | } |
| 135 | return pubkeys, int(nrequired), nil |
| 136 | } |
| 137 | |
| 138 | func checkMultiSigParams(nrequired, npubkeys int64) error { |
| 139 | if nrequired < 0 { |