github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/transaction/witness_condition.go (about) 1 package transaction 2 3 import ( 4 "encoding/json" 5 "errors" 6 "math/big" 7 8 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 9 "github.com/nspcc-dev/neo-go/pkg/io" 10 "github.com/nspcc-dev/neo-go/pkg/util" 11 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 12 ) 13 14 //go:generate stringer -type=WitnessConditionType -linecomment 15 16 // WitnessConditionType encodes a type of witness condition. 17 type WitnessConditionType byte 18 19 const ( 20 // WitnessBoolean is a generic boolean condition. 21 WitnessBoolean WitnessConditionType = 0x00 // Boolean 22 // WitnessNot reverses another condition. 23 WitnessNot WitnessConditionType = 0x01 // Not 24 // WitnessAnd means that all conditions must be met. 25 WitnessAnd WitnessConditionType = 0x02 // And 26 // WitnessOr means that any of conditions must be met. 27 WitnessOr WitnessConditionType = 0x03 // Or 28 // WitnessScriptHash matches executing contract's script hash. 29 WitnessScriptHash WitnessConditionType = 0x18 // ScriptHash 30 // WitnessGroup matches executing contract's group key. 31 WitnessGroup WitnessConditionType = 0x19 // Group 32 // WitnessCalledByEntry matches when current script is an entry script or is called by an entry script. 33 WitnessCalledByEntry WitnessConditionType = 0x20 // CalledByEntry 34 // WitnessCalledByContract matches when current script is called by the specified contract. 35 WitnessCalledByContract WitnessConditionType = 0x28 // CalledByContract 36 // WitnessCalledByGroup matches when current script is called by contract belonging to the specified group. 37 WitnessCalledByGroup WitnessConditionType = 0x29 // CalledByGroup 38 39 // MaxConditionNesting limits the maximum allowed level of condition nesting. 40 MaxConditionNesting = 2 41 ) 42 43 // WitnessCondition is a condition of WitnessRule. 44 type WitnessCondition interface { 45 // Type returns a type of this condition. 46 Type() WitnessConditionType 47 // Match checks whether this condition matches current context. 48 Match(MatchContext) (bool, error) 49 // EncodeBinary allows to serialize condition to its binary 50 // representation (including type data). 51 EncodeBinary(*io.BinWriter) 52 // DecodeBinarySpecific decodes type-specific binary data from the given 53 // reader (not including type data). 54 DecodeBinarySpecific(*io.BinReader, int) 55 // ToStackItem converts WitnessCondition to stackitem.Item. 56 ToStackItem() stackitem.Item 57 // Copy returns a deep copy of the condition. 58 Copy() WitnessCondition 59 60 json.Marshaler 61 } 62 63 // MatchContext is a set of methods from execution engine needed to perform the 64 // witness check. 65 type MatchContext interface { 66 GetCallingScriptHash() util.Uint160 67 GetCurrentScriptHash() util.Uint160 68 CallingScriptHasGroup(*keys.PublicKey) (bool, error) 69 CurrentScriptHasGroup(*keys.PublicKey) (bool, error) 70 IsCalledByEntry() bool 71 } 72 73 type ( 74 // ConditionBoolean is a boolean condition type. 75 ConditionBoolean bool 76 // ConditionNot inverses the meaning of contained condition. 77 ConditionNot struct { 78 Condition WitnessCondition 79 } 80 // ConditionAnd is a set of conditions required to match. 81 ConditionAnd []WitnessCondition 82 // ConditionOr is a set of conditions one of which is required to match. 83 ConditionOr []WitnessCondition 84 // ConditionScriptHash is a condition matching executing script hash. 85 ConditionScriptHash util.Uint160 86 // ConditionGroup is a condition matching executing script group. 87 ConditionGroup keys.PublicKey 88 // ConditionCalledByEntry is a condition matching entry script or one directly called by it. 89 ConditionCalledByEntry struct{} 90 // ConditionCalledByContract is a condition matching calling script hash. 91 ConditionCalledByContract util.Uint160 92 // ConditionCalledByGroup is a condition matching calling script group. 93 ConditionCalledByGroup keys.PublicKey 94 ) 95 96 // conditionAux is used for JSON marshaling/unmarshaling. 97 type conditionAux struct { 98 Expression json.RawMessage `json:"expression,omitempty"` // Can be either boolean or conditionAux. 99 Expressions []json.RawMessage `json:"expressions,omitempty"` 100 Group *keys.PublicKey `json:"group,omitempty"` 101 Hash *util.Uint160 `json:"hash,omitempty"` 102 Type string `json:"type"` 103 } 104 105 // Type implements the WitnessCondition interface and returns condition type. 106 func (c *ConditionBoolean) Type() WitnessConditionType { 107 return WitnessBoolean 108 } 109 110 // Match implements the WitnessCondition interface checking whether this condition 111 // matches given context. 112 func (c *ConditionBoolean) Match(_ MatchContext) (bool, error) { 113 return bool(*c), nil 114 } 115 116 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 117 func (c *ConditionBoolean) EncodeBinary(w *io.BinWriter) { 118 w.WriteB(byte(c.Type())) 119 w.WriteBool(bool(*c)) 120 } 121 122 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 123 // deserialize condition-specific data. 124 func (c *ConditionBoolean) DecodeBinarySpecific(r *io.BinReader, maxDepth int) { 125 *c = ConditionBoolean(r.ReadBool()) 126 } 127 128 // MarshalJSON implements the json.Marshaler interface. 129 func (c *ConditionBoolean) MarshalJSON() ([]byte, error) { 130 boolJSON, _ := json.Marshal(bool(*c)) // Simple boolean can't fail. 131 aux := conditionAux{ 132 Type: c.Type().String(), 133 Expression: json.RawMessage(boolJSON), 134 } 135 return json.Marshal(aux) 136 } 137 138 // ToStackItem implements WitnessCondition interface allowing to convert 139 // to stackitem.Item. 140 func (c *ConditionBoolean) ToStackItem() stackitem.Item { 141 return condToStackItem(c.Type(), bool(*c)) 142 } 143 144 // Copy returns a deep copy of the condition. 145 func (c *ConditionBoolean) Copy() WitnessCondition { 146 cc := *c 147 return &cc 148 } 149 150 // Type implements the WitnessCondition interface and returns condition type. 151 func (c *ConditionNot) Type() WitnessConditionType { 152 return WitnessNot 153 } 154 155 // Match implements the WitnessCondition interface checking whether this condition 156 // matches given context. 157 func (c *ConditionNot) Match(ctx MatchContext) (bool, error) { 158 res, err := c.Condition.Match(ctx) 159 return ((err == nil) && !res), err 160 } 161 162 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 163 func (c *ConditionNot) EncodeBinary(w *io.BinWriter) { 164 w.WriteB(byte(c.Type())) 165 c.Condition.EncodeBinary(w) 166 } 167 168 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 169 // deserialize condition-specific data. 170 func (c *ConditionNot) DecodeBinarySpecific(r *io.BinReader, maxDepth int) { 171 c.Condition = decodeBinaryCondition(r, maxDepth-1) 172 } 173 174 // MarshalJSON implements the json.Marshaler interface. 175 func (c *ConditionNot) MarshalJSON() ([]byte, error) { 176 condJSON, err := json.Marshal(c.Condition) 177 if err != nil { 178 return nil, err 179 } 180 aux := conditionAux{ 181 Type: c.Type().String(), 182 Expression: json.RawMessage(condJSON), 183 } 184 return json.Marshal(aux) 185 } 186 187 // ToStackItem implements the WitnessCondition interface allowing to convert 188 // to stackitem.Item. 189 func (c *ConditionNot) ToStackItem() stackitem.Item { 190 return condToStackItem(c.Type(), c.Condition) 191 } 192 193 // Copy implements the WitnessCondition interface and returns a deep copy of the condition. 194 func (c *ConditionNot) Copy() WitnessCondition { 195 cp := *c 196 return &cp 197 } 198 199 // Type implements the WitnessCondition interface and returns condition type. 200 func (c *ConditionAnd) Type() WitnessConditionType { 201 return WitnessAnd 202 } 203 204 // Match implements the WitnessCondition interface checking whether this condition 205 // matches given context. 206 func (c *ConditionAnd) Match(ctx MatchContext) (bool, error) { 207 for _, cond := range *c { 208 res, err := cond.Match(ctx) 209 if err != nil { 210 return false, err 211 } 212 if !res { 213 return false, nil 214 } 215 } 216 return true, nil 217 } 218 219 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 220 func (c *ConditionAnd) EncodeBinary(w *io.BinWriter) { 221 w.WriteB(byte(c.Type())) 222 w.WriteArray([]WitnessCondition(*c)) 223 } 224 225 func readArrayOfConditions(r *io.BinReader, maxDepth int) []WitnessCondition { 226 l := r.ReadVarUint() 227 if l == 0 { 228 r.Err = errors.New("empty array of conditions") 229 return nil 230 } 231 if l > maxSubitems { 232 r.Err = errors.New("too many elements") 233 return nil 234 } 235 a := make([]WitnessCondition, l) 236 for i := 0; i < int(l); i++ { 237 a[i] = decodeBinaryCondition(r, maxDepth-1) 238 } 239 if r.Err != nil { 240 return nil 241 } 242 return a 243 } 244 245 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 246 // deserialize condition-specific data. 247 func (c *ConditionAnd) DecodeBinarySpecific(r *io.BinReader, maxDepth int) { 248 a := readArrayOfConditions(r, maxDepth) 249 if r.Err == nil { 250 *c = a 251 } 252 } 253 254 func arrayToJSON(c WitnessCondition, a []WitnessCondition) ([]byte, error) { 255 exprs := make([]json.RawMessage, len(a)) 256 for i := 0; i < len(a); i++ { 257 b, err := a[i].MarshalJSON() 258 if err != nil { 259 return nil, err 260 } 261 exprs[i] = json.RawMessage(b) 262 } 263 aux := conditionAux{ 264 Type: c.Type().String(), 265 Expressions: exprs, 266 } 267 return json.Marshal(aux) 268 } 269 270 // MarshalJSON implements the json.Marshaler interface. 271 func (c *ConditionAnd) MarshalJSON() ([]byte, error) { 272 return arrayToJSON(c, []WitnessCondition(*c)) 273 } 274 275 // ToStackItem implements the WitnessCondition interface allowing to convert 276 // to stackitem.Item. 277 func (c *ConditionAnd) ToStackItem() stackitem.Item { 278 return condToStackItem(c.Type(), []WitnessCondition(*c)) 279 } 280 281 // Copy implements the WitnessCondition interface and returns a deep copy of the condition. 282 func (c *ConditionAnd) Copy() WitnessCondition { 283 cp := make(ConditionAnd, len(*c)) 284 for i, cond := range *c { 285 cp[i] = cond.Copy() 286 } 287 return &cp 288 } 289 290 // Type implements the WitnessCondition interface and returns condition type. 291 func (c *ConditionOr) Type() WitnessConditionType { 292 return WitnessOr 293 } 294 295 // Match implements the WitnessCondition interface checking whether this condition 296 // matches given context. 297 func (c *ConditionOr) Match(ctx MatchContext) (bool, error) { 298 for _, cond := range *c { 299 res, err := cond.Match(ctx) 300 if err != nil { 301 return false, err 302 } 303 if res { 304 return true, nil 305 } 306 } 307 return false, nil 308 } 309 310 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 311 func (c *ConditionOr) EncodeBinary(w *io.BinWriter) { 312 w.WriteB(byte(c.Type())) 313 w.WriteArray([]WitnessCondition(*c)) 314 } 315 316 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 317 // deserialize condition-specific data. 318 func (c *ConditionOr) DecodeBinarySpecific(r *io.BinReader, maxDepth int) { 319 a := readArrayOfConditions(r, maxDepth) 320 if r.Err == nil { 321 *c = a 322 } 323 } 324 325 // MarshalJSON implements the json.Marshaler interface. 326 func (c *ConditionOr) MarshalJSON() ([]byte, error) { 327 return arrayToJSON(c, []WitnessCondition(*c)) 328 } 329 330 // ToStackItem implements the WitnessCondition interface allowing to convert 331 // to stackitem.Item. 332 func (c *ConditionOr) ToStackItem() stackitem.Item { 333 return condToStackItem(c.Type(), []WitnessCondition(*c)) 334 } 335 336 // Copy implements the WitnessCondition interface and returns a deep copy of the condition. 337 func (c *ConditionOr) Copy() WitnessCondition { 338 cp := make(ConditionOr, len(*c)) 339 for i, cond := range *c { 340 cp[i] = cond.Copy() 341 } 342 return &cp 343 } 344 345 // Type implements the WitnessCondition interface and returns condition type. 346 func (c *ConditionScriptHash) Type() WitnessConditionType { 347 return WitnessScriptHash 348 } 349 350 // Match implements the WitnessCondition interface checking whether this condition 351 // matches given context. 352 func (c *ConditionScriptHash) Match(ctx MatchContext) (bool, error) { 353 return util.Uint160(*c).Equals(ctx.GetCurrentScriptHash()), nil 354 } 355 356 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 357 func (c *ConditionScriptHash) EncodeBinary(w *io.BinWriter) { 358 w.WriteB(byte(c.Type())) 359 w.WriteBytes(c[:]) 360 } 361 362 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 363 // deserialize condition-specific data. 364 func (c *ConditionScriptHash) DecodeBinarySpecific(r *io.BinReader, _ int) { 365 r.ReadBytes(c[:]) 366 } 367 368 // MarshalJSON implements the json.Marshaler interface. 369 func (c *ConditionScriptHash) MarshalJSON() ([]byte, error) { 370 aux := conditionAux{ 371 Type: c.Type().String(), 372 Hash: (*util.Uint160)(c), 373 } 374 return json.Marshal(aux) 375 } 376 377 // ToStackItem implements the WitnessCondition interface allowing to convert 378 // to stackitem.Item. 379 func (c *ConditionScriptHash) ToStackItem() stackitem.Item { 380 return condToStackItem(c.Type(), util.Uint160(*c)) 381 } 382 383 // Copy implements the WitnessCondition interface and returns a deep copy of the condition. 384 func (c *ConditionScriptHash) Copy() WitnessCondition { 385 cc := *c 386 return &cc 387 } 388 389 // Type implements the WitnessCondition interface and returns condition type. 390 func (c *ConditionGroup) Type() WitnessConditionType { 391 return WitnessGroup 392 } 393 394 // Match implements the WitnessCondition interface checking whether this condition 395 // matches given context. 396 func (c *ConditionGroup) Match(ctx MatchContext) (bool, error) { 397 return ctx.CurrentScriptHasGroup((*keys.PublicKey)(c)) 398 } 399 400 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 401 func (c *ConditionGroup) EncodeBinary(w *io.BinWriter) { 402 w.WriteB(byte(c.Type())) 403 (*keys.PublicKey)(c).EncodeBinary(w) 404 } 405 406 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 407 // deserialize condition-specific data. 408 func (c *ConditionGroup) DecodeBinarySpecific(r *io.BinReader, _ int) { 409 (*keys.PublicKey)(c).DecodeBinary(r) 410 } 411 412 // MarshalJSON implements the json.Marshaler interface. 413 func (c *ConditionGroup) MarshalJSON() ([]byte, error) { 414 aux := conditionAux{ 415 Type: c.Type().String(), 416 Group: (*keys.PublicKey)(c), 417 } 418 return json.Marshal(aux) 419 } 420 421 // ToStackItem implements the WitnessCondition interface allowing to convert 422 // to stackitem.Item. 423 func (c *ConditionGroup) ToStackItem() stackitem.Item { 424 return condToStackItem(c.Type(), keys.PublicKey(*c)) 425 } 426 427 // Copy implements the WitnessCondition interface and returns a deep copy of the condition. 428 func (c *ConditionGroup) Copy() WitnessCondition { 429 cp := *c 430 return &cp 431 } 432 433 // Type implements the WitnessCondition interface and returns condition type. 434 func (c ConditionCalledByEntry) Type() WitnessConditionType { 435 return WitnessCalledByEntry 436 } 437 438 // Match implements the WitnessCondition interface checking whether this condition 439 // matches given context. 440 func (c ConditionCalledByEntry) Match(ctx MatchContext) (bool, error) { 441 return ctx.IsCalledByEntry(), nil 442 } 443 444 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 445 func (c ConditionCalledByEntry) EncodeBinary(w *io.BinWriter) { 446 w.WriteB(byte(c.Type())) 447 } 448 449 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 450 // deserialize condition-specific data. 451 func (c ConditionCalledByEntry) DecodeBinarySpecific(_ *io.BinReader, _ int) { 452 } 453 454 // MarshalJSON implements the json.Marshaler interface. 455 func (c ConditionCalledByEntry) MarshalJSON() ([]byte, error) { 456 aux := conditionAux{ 457 Type: c.Type().String(), 458 } 459 return json.Marshal(aux) 460 } 461 462 // ToStackItem implements the WitnessCondition interface allowing to convert 463 // to stackitem.Item. 464 func (c ConditionCalledByEntry) ToStackItem() stackitem.Item { 465 return condToStackItem(c.Type(), nil) 466 } 467 468 // Copy implements the WitnessCondition interface and returns a deep copy of the condition. 469 func (c ConditionCalledByEntry) Copy() WitnessCondition { 470 return ConditionCalledByEntry{} 471 } 472 473 // Type implements the WitnessCondition interface and returns condition type. 474 func (c *ConditionCalledByContract) Type() WitnessConditionType { 475 return WitnessCalledByContract 476 } 477 478 // Match implements the WitnessCondition interface checking whether this condition 479 // matches given context. 480 func (c *ConditionCalledByContract) Match(ctx MatchContext) (bool, error) { 481 return util.Uint160(*c).Equals(ctx.GetCallingScriptHash()), nil 482 } 483 484 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 485 func (c *ConditionCalledByContract) EncodeBinary(w *io.BinWriter) { 486 w.WriteB(byte(c.Type())) 487 w.WriteBytes(c[:]) 488 } 489 490 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 491 // deserialize condition-specific data. 492 func (c *ConditionCalledByContract) DecodeBinarySpecific(r *io.BinReader, _ int) { 493 r.ReadBytes(c[:]) 494 } 495 496 // MarshalJSON implements the json.Marshaler interface. 497 func (c *ConditionCalledByContract) MarshalJSON() ([]byte, error) { 498 aux := conditionAux{ 499 Type: c.Type().String(), 500 Hash: (*util.Uint160)(c), 501 } 502 return json.Marshal(aux) 503 } 504 505 // ToStackItem implements the WitnessCondition interface allowing to convert 506 // to stackitem.Item. 507 func (c *ConditionCalledByContract) ToStackItem() stackitem.Item { 508 return condToStackItem(c.Type(), util.Uint160(*c)) 509 } 510 511 // Copy implements the WitnessCondition interface and returns a deep copy of the condition. 512 func (c *ConditionCalledByContract) Copy() WitnessCondition { 513 cc := *c 514 return &cc 515 } 516 517 // Type implements the WitnessCondition interface and returns condition type. 518 func (c *ConditionCalledByGroup) Type() WitnessConditionType { 519 return WitnessCalledByGroup 520 } 521 522 // Match implements the WitnessCondition interface checking whether this condition 523 // matches given context. 524 func (c *ConditionCalledByGroup) Match(ctx MatchContext) (bool, error) { 525 return ctx.CallingScriptHasGroup((*keys.PublicKey)(c)) 526 } 527 528 // EncodeBinary implements the WitnessCondition interface allowing to serialize condition. 529 func (c *ConditionCalledByGroup) EncodeBinary(w *io.BinWriter) { 530 w.WriteB(byte(c.Type())) 531 (*keys.PublicKey)(c).EncodeBinary(w) 532 } 533 534 // DecodeBinarySpecific implements the WitnessCondition interface allowing to 535 // deserialize condition-specific data. 536 func (c *ConditionCalledByGroup) DecodeBinarySpecific(r *io.BinReader, _ int) { 537 (*keys.PublicKey)(c).DecodeBinary(r) 538 } 539 540 // MarshalJSON implements the json.Marshaler interface. 541 func (c *ConditionCalledByGroup) MarshalJSON() ([]byte, error) { 542 aux := conditionAux{ 543 Type: c.Type().String(), 544 Group: (*keys.PublicKey)(c), 545 } 546 return json.Marshal(aux) 547 } 548 549 // ToStackItem implements WitnessCondition interface allowing to convert 550 // to stackitem.Item. 551 func (c *ConditionCalledByGroup) ToStackItem() stackitem.Item { 552 return condToStackItem(c.Type(), keys.PublicKey(*c)) 553 } 554 555 // Copy implements the WitnessCondition interface and returns a deep copy of the condition. 556 func (c *ConditionCalledByGroup) Copy() WitnessCondition { 557 cp := *c 558 return &cp 559 } 560 561 // DecodeBinaryCondition decodes and returns condition from the given binary stream. 562 func DecodeBinaryCondition(r *io.BinReader) WitnessCondition { 563 return decodeBinaryCondition(r, MaxConditionNesting) 564 } 565 566 func decodeBinaryCondition(r *io.BinReader, maxDepth int) WitnessCondition { 567 if maxDepth <= 0 { 568 r.Err = errors.New("too many nesting levels") 569 return nil 570 } 571 t := WitnessConditionType(r.ReadB()) 572 if r.Err != nil { 573 return nil 574 } 575 var res WitnessCondition 576 switch t { 577 case WitnessBoolean: 578 var v ConditionBoolean 579 res = &v 580 case WitnessNot: 581 res = &ConditionNot{} 582 case WitnessAnd: 583 res = &ConditionAnd{} 584 case WitnessOr: 585 res = &ConditionOr{} 586 case WitnessScriptHash: 587 res = &ConditionScriptHash{} 588 case WitnessGroup: 589 res = &ConditionGroup{} 590 case WitnessCalledByEntry: 591 res = ConditionCalledByEntry{} 592 case WitnessCalledByContract: 593 res = &ConditionCalledByContract{} 594 case WitnessCalledByGroup: 595 res = &ConditionCalledByGroup{} 596 default: 597 r.Err = errors.New("invalid condition type") 598 return nil 599 } 600 res.DecodeBinarySpecific(r, maxDepth) 601 if r.Err != nil { 602 return nil 603 } 604 return res 605 } 606 607 func unmarshalArrayOfConditionJSONs(arr []json.RawMessage, maxDepth int) ([]WitnessCondition, error) { 608 l := len(arr) 609 if l == 0 { 610 return nil, errors.New("empty array of conditions") 611 } 612 if l > maxSubitems { 613 return nil, errors.New("too many elements") 614 } 615 res := make([]WitnessCondition, l) 616 for i := range arr { 617 v, err := unmarshalConditionJSON(arr[i], maxDepth-1) 618 if err != nil { 619 return nil, err 620 } 621 res[i] = v 622 } 623 return res, nil 624 } 625 626 // UnmarshalConditionJSON unmarshalls condition from the given JSON data. 627 func UnmarshalConditionJSON(data []byte) (WitnessCondition, error) { 628 return unmarshalConditionJSON(data, MaxConditionNesting) 629 } 630 631 func unmarshalConditionJSON(data []byte, maxDepth int) (WitnessCondition, error) { 632 if maxDepth <= 0 { 633 return nil, errors.New("too many nesting levels") 634 } 635 aux := &conditionAux{} 636 err := json.Unmarshal(data, aux) 637 if err != nil { 638 return nil, err 639 } 640 var res WitnessCondition 641 switch aux.Type { 642 case WitnessBoolean.String(): 643 var v bool 644 err = json.Unmarshal(aux.Expression, &v) 645 if err != nil { 646 return nil, err 647 } 648 res = (*ConditionBoolean)(&v) 649 case WitnessNot.String(): 650 v, err := unmarshalConditionJSON(aux.Expression, maxDepth-1) 651 if err != nil { 652 return nil, err 653 } 654 res = &ConditionNot{Condition: v} 655 case WitnessAnd.String(): 656 v, err := unmarshalArrayOfConditionJSONs(aux.Expressions, maxDepth) 657 if err != nil { 658 return nil, err 659 } 660 res = (*ConditionAnd)(&v) 661 case WitnessOr.String(): 662 v, err := unmarshalArrayOfConditionJSONs(aux.Expressions, maxDepth) 663 if err != nil { 664 return nil, err 665 } 666 res = (*ConditionOr)(&v) 667 case WitnessScriptHash.String(): 668 if aux.Hash == nil { 669 return nil, errors.New("no hash specified") 670 } 671 res = (*ConditionScriptHash)(aux.Hash) 672 case WitnessGroup.String(): 673 if aux.Group == nil { 674 return nil, errors.New("no group specified") 675 } 676 res = (*ConditionGroup)(aux.Group) 677 case WitnessCalledByEntry.String(): 678 res = ConditionCalledByEntry{} 679 case WitnessCalledByContract.String(): 680 if aux.Hash == nil { 681 return nil, errors.New("no hash specified") 682 } 683 res = (*ConditionCalledByContract)(aux.Hash) 684 case WitnessCalledByGroup.String(): 685 if aux.Group == nil { 686 return nil, errors.New("no group specified") 687 } 688 res = (*ConditionCalledByGroup)(aux.Group) 689 default: 690 return nil, errors.New("invalid condition type") 691 } 692 return res, nil 693 } 694 695 func condToStackItem(typ WitnessConditionType, c any) stackitem.Item { 696 res := make([]stackitem.Item, 0, 2) 697 res = append(res, stackitem.NewBigInteger(big.NewInt(int64(typ)))) 698 switch typ { 699 case WitnessBoolean: 700 res = append(res, stackitem.NewBool(c.(bool))) 701 case WitnessNot: 702 res = append(res, c.(WitnessCondition).ToStackItem()) 703 case WitnessAnd, WitnessOr: 704 v := c.([]WitnessCondition) 705 operands := make([]stackitem.Item, len(v)) 706 for i, op := range v { 707 operands[i] = op.ToStackItem() 708 } 709 res = append(res, stackitem.NewArray(operands)) 710 case WitnessScriptHash, WitnessCalledByContract: 711 res = append(res, stackitem.NewByteArray(c.(util.Uint160).BytesBE())) 712 case WitnessGroup, WitnessCalledByGroup: 713 g := c.(keys.PublicKey) 714 res = append(res, stackitem.NewByteArray((&g).Bytes())) 715 case WitnessCalledByEntry: 716 // No additional item should be added. 717 } 718 return stackitem.NewArray(res) 719 }