forked from kevink1103/cardano-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.go
167 lines (147 loc) · 3.8 KB
/
script.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package cardano
import (
"fmt"
"github.com/echovl/cardano-go/crypto"
)
type ScriptHashNamespace uint8
const (
NativeScriptNamespace ScriptHashNamespace = iota
PlutusScriptNamespace
)
type NativeScriptType uint64
const (
ScriptPubKey NativeScriptType = iota
ScriptAll
ScriptAny
ScriptNofK
ScriptInvalidBefore
ScriptInvalidAfter
)
type scriptPubKey struct {
_ struct{} `cbor:"_,toarray"`
Type NativeScriptType
KeyHash AddrKeyHash
}
type scriptAll struct {
_ struct{} `cbor:"_,toarray"`
Type NativeScriptType
Scripts []NativeScript
}
type scriptAny struct {
_ struct{} `cbor:"_,toarray"`
Type NativeScriptType
Scripts []NativeScript
}
type scriptNofK struct {
_ struct{} `cbor:"_,toarray"`
Type NativeScriptType
N uint64
Scripts []NativeScript
}
type scriptInvalidBefore struct {
_ struct{} `cbor:"_,toarray"`
Type NativeScriptType
IntervalValue uint64
}
type scriptInvalidAfter struct {
_ struct{} `cbor:"_,toarray"`
Type NativeScriptType
IntervalValue uint64
}
// NativeScript is a Cardano Native Script.
type NativeScript struct {
Type NativeScriptType
KeyHash AddrKeyHash
N uint64
Scripts []NativeScript
IntervalValue uint64
}
// NewScriptPubKey returns a new Script PubKey.
func NewScriptPubKey(publicKey crypto.PubKey) (NativeScript, error) {
keyHash, err := publicKey.Hash()
if err != nil {
return NativeScript{}, err
}
return NativeScript{Type: ScriptPubKey, KeyHash: keyHash}, nil
}
// Hash returns the script hash using blake2b224.
func (ns *NativeScript) Hash() (Hash28, error) {
bytes, err := ns.Bytes()
if err != nil {
return nil, err
}
bytes = append([]byte{byte(NativeScriptNamespace)}, bytes...)
return Blake224Hash(append(bytes))
}
// Bytes returns the CBOR encoding of the script as bytes.
func (ns *NativeScript) Bytes() ([]byte, error) {
return cborEnc.Marshal(ns)
}
// MarshalCBOR implements cbor.Marshaler.
func (ns *NativeScript) MarshalCBOR() ([]byte, error) {
var script []interface{}
switch ns.Type {
case ScriptPubKey:
script = append(script, ns.Type, ns.KeyHash)
case ScriptAll, ScriptAny:
script = append(script, ns.Type, ns.Scripts)
case ScriptNofK:
script = append(script, ns.Type, ns.N, ns.Scripts)
case ScriptInvalidBefore, ScriptInvalidAfter:
script = append(script, ns.Type, ns.IntervalValue)
}
return cborEnc.Marshal(script)
}
// UnmarshalCBOR implements cbor.Unmarshaler.
func (ns *NativeScript) UnmarshalCBOR(data []byte) error {
nsType, err := getTypeFromCBORArray(data)
if err != nil {
return fmt.Errorf("cbor: cannot unmarshal CBOR array into StakeCredential (%v)", err)
}
switch NativeScriptType(nsType) {
case ScriptPubKey:
script := scriptPubKey{}
if err := cborDec.Unmarshal(data, &script); err != nil {
return err
}
ns.Type = script.Type
ns.KeyHash = script.KeyHash
case ScriptAll:
script := scriptAll{}
if err := cborDec.Unmarshal(data, &script); err != nil {
return err
}
ns.Type = script.Type
ns.Scripts = script.Scripts
case ScriptAny:
script := scriptAny{}
if err := cborDec.Unmarshal(data, &script); err != nil {
return err
}
ns.Type = script.Type
ns.Scripts = script.Scripts
case ScriptNofK:
script := scriptNofK{}
if err := cborDec.Unmarshal(data, &script); err != nil {
return err
}
ns.Type = script.Type
ns.N = script.N
ns.Scripts = script.Scripts
case ScriptInvalidBefore:
script := scriptInvalidBefore{}
if err := cborDec.Unmarshal(data, &script); err != nil {
return err
}
ns.Type = script.Type
ns.IntervalValue = script.IntervalValue
case ScriptInvalidAfter:
script := scriptInvalidAfter{}
if err := cborDec.Unmarshal(data, &script); err != nil {
return err
}
ns.Type = script.Type
ns.IntervalValue = script.IntervalValue
}
return nil
}