github.com/braveheart12/just@v0.8.7/ledger/artifactmanager/artifactmanager.go (about) 1 /* 2 * Copyright 2019 Insolar Technologies 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package artifactmanager 18 19 import ( 20 "bytes" 21 "context" 22 "fmt" 23 24 "github.com/pkg/errors" 25 "go.opencensus.io/trace" 26 27 "github.com/insolar/insolar/core" 28 "github.com/insolar/insolar/core/message" 29 "github.com/insolar/insolar/core/reply" 30 "github.com/insolar/insolar/instrumentation/instracer" 31 "github.com/insolar/insolar/ledger/storage" 32 "github.com/insolar/insolar/ledger/storage/record" 33 ) 34 35 const ( 36 getChildrenChunkSize = 10 * 1000 37 jetMissRetryCount = 10 38 ) 39 40 // LedgerArtifactManager provides concrete API to storage for processing module. 41 type LedgerArtifactManager struct { 42 DB storage.DBContext `inject:""` 43 GenesisState storage.GenesisState `inject:""` 44 JetStorage storage.JetStorage `inject:""` 45 46 DefaultBus core.MessageBus `inject:""` 47 PlatformCryptographyScheme core.PlatformCryptographyScheme `inject:""` 48 PulseStorage core.PulseStorage `inject:""` 49 JetCoordinator core.JetCoordinator `inject:""` 50 51 getChildrenChunkSize int 52 senders *ledgerArtifactSenders 53 } 54 55 // State returns hash state for artifact manager. 56 func (m *LedgerArtifactManager) State() ([]byte, error) { 57 // This is a temporary stab to simulate real hash. 58 return m.PlatformCryptographyScheme.IntegrityHasher().Hash([]byte{1, 2, 3}), nil 59 } 60 61 // NewArtifactManger creates new manager instance. 62 func NewArtifactManger() *LedgerArtifactManager { 63 return &LedgerArtifactManager{ 64 getChildrenChunkSize: getChildrenChunkSize, 65 senders: newLedgerArtifactSenders(), 66 } 67 } 68 69 // GenesisRef returns the root record reference. 70 // 71 // Root record is the parent for all top-level records. 72 func (m *LedgerArtifactManager) GenesisRef() *core.RecordRef { 73 return m.GenesisState.GenesisRef() 74 } 75 76 // RegisterRequest sends message for request registration, 77 // returns request record Ref if request successfully created or already exists. 78 func (m *LedgerArtifactManager) RegisterRequest( 79 ctx context.Context, obj core.RecordRef, parcel core.Parcel, 80 ) (*core.RecordID, error) { 81 var err error 82 ctx, span := instracer.StartSpan(ctx, "artifactmanager.RegisterRequest") 83 instrumenter := instrument(ctx, "RegisterRequest").err(&err) 84 defer func() { 85 if err != nil { 86 span.AddAttributes(trace.StringAttribute("error", err.Error())) 87 } 88 span.End() 89 instrumenter.end() 90 }() 91 92 currentPN, err := m.pulse(ctx) 93 if err != nil { 94 return nil, err 95 } 96 97 rec := &record.RequestRecord{ 98 Parcel: message.ParcelToBytes(parcel), 99 MessageHash: m.PlatformCryptographyScheme.IntegrityHasher().Hash(message.MustSerializeBytes(parcel.Message())), 100 Object: *obj.Record(), 101 } 102 recID := record.NewRecordIDFromRecord( 103 m.PlatformCryptographyScheme, 104 currentPN, 105 rec) 106 recRef := core.NewRecordRef(*parcel.DefaultTarget().Domain(), *recID) 107 id, err := m.setRecord( 108 ctx, 109 rec, 110 *recRef, 111 ) 112 return id, errors.Wrap(err, "[ RegisterRequest ] ") 113 } 114 115 // GetCode returns code from code record by provided reference according to provided machine preference. 116 // 117 // This method is used by VM to fetch code for execution. 118 func (m *LedgerArtifactManager) GetCode( 119 ctx context.Context, code core.RecordRef, 120 ) (core.CodeDescriptor, error) { 121 var err error 122 instrumenter := instrument(ctx, "GetCode").err(&err) 123 ctx, span := instracer.StartSpan(ctx, "artifactmanager.GetCode") 124 defer func() { 125 if err != nil { 126 span.AddAttributes(trace.StringAttribute("error", err.Error())) 127 } 128 span.End() 129 instrumenter.end() 130 }() 131 132 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 133 sender := BuildSender( 134 bus.Send, 135 m.senders.cachedSender(m.PlatformCryptographyScheme), 136 followRedirectSender(bus), 137 retryJetSender(m.JetStorage), 138 ) 139 140 genericReact, err := sender(ctx, &message.GetCode{Code: code}, nil) 141 142 if err != nil { 143 return nil, err 144 } 145 146 switch rep := genericReact.(type) { 147 case *reply.Code: 148 desc := CodeDescriptor{ 149 ctx: ctx, 150 ref: code, 151 machineType: rep.MachineType, 152 code: rep.Code, 153 } 154 return &desc, nil 155 case *reply.Error: 156 return nil, rep.Error() 157 default: 158 return nil, fmt.Errorf("GetCode: unexpected reply: %#v", rep) 159 } 160 } 161 162 // GetObject returns descriptor for provided state. 163 // 164 // If provided state is nil, the latest state will be returned (with deactivation check). Returned descriptor will 165 // provide methods for fetching all related data. 166 func (m *LedgerArtifactManager) GetObject( 167 ctx context.Context, 168 head core.RecordRef, 169 state *core.RecordID, 170 approved bool, 171 ) (core.ObjectDescriptor, error) { 172 var ( 173 desc *ObjectDescriptor 174 err error 175 ) 176 ctx, span := instracer.StartSpan(ctx, "artifactmanager.Getobject") 177 instrumenter := instrument(ctx, "GetObject").err(&err) 178 defer func() { 179 if err != nil { 180 span.AddAttributes(trace.StringAttribute("error", err.Error())) 181 } 182 span.End() 183 if err != nil && err == ErrObjectDeactivated { 184 err = nil // megahack: threat it 2xx 185 } 186 instrumenter.end() 187 }() 188 189 getObjectMsg := &message.GetObject{ 190 Head: head, 191 State: state, 192 Approved: approved, 193 } 194 195 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 196 sender := BuildSender( 197 bus.Send, 198 followRedirectSender(bus), 199 retryJetSender(m.JetStorage), 200 ) 201 202 genericReact, err := sender(ctx, getObjectMsg, nil) 203 if err != nil { 204 return nil, err 205 } 206 207 switch r := genericReact.(type) { 208 case *reply.Object: 209 desc = &ObjectDescriptor{ 210 ctx: ctx, 211 am: m, 212 head: r.Head, 213 state: r.State, 214 prototype: r.Prototype, 215 isPrototype: r.IsPrototype, 216 childPointer: r.ChildPointer, 217 memory: r.Memory, 218 parent: r.Parent, 219 } 220 return desc, err 221 case *reply.Error: 222 return nil, r.Error() 223 default: 224 return nil, fmt.Errorf("GetObject: unexpected reply: %#v", genericReact) 225 } 226 } 227 228 // GetPendingRequest returns an unclosed pending request 229 // It takes an id from current LME 230 // Then goes either to a light node or heavy node 231 func (m *LedgerArtifactManager) GetPendingRequest(ctx context.Context, objectID core.RecordID) (core.Parcel, error) { 232 var err error 233 instrumenter := instrument(ctx, "GetRegisterRequest").err(&err) 234 ctx, span := instracer.StartSpan(ctx, "artifactmanager.GetRegisterRequest") 235 defer func() { 236 if err != nil { 237 span.AddAttributes(trace.StringAttribute("error", err.Error())) 238 } 239 span.End() 240 instrumenter.end() 241 }() 242 243 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 244 sender := BuildSender( 245 bus.Send, 246 retryJetSender(m.JetStorage), 247 ) 248 249 genericReply, err := sender(ctx, &message.GetPendingRequestID{ 250 ObjectID: objectID, 251 }, nil) 252 if err != nil { 253 return nil, err 254 } 255 256 var requestID core.RecordID 257 switch r := genericReply.(type) { 258 case *reply.ID: 259 requestID = r.ID 260 case *reply.Error: 261 return nil, r.Error() 262 default: 263 return nil, fmt.Errorf("GetPendingRequest: unexpected reply: %#v", genericReply) 264 } 265 266 currentPN, err := m.pulse(ctx) 267 if err != nil { 268 return nil, err 269 } 270 271 node, err := m.JetCoordinator.NodeForObject(ctx, objectID, currentPN, requestID.Pulse()) 272 if err != nil { 273 return nil, err 274 } 275 276 sender = BuildSender( 277 bus.Send, 278 retryJetSender(m.JetStorage), 279 ) 280 genericReply, err = sender( 281 ctx, 282 &message.GetRequest{ 283 Request: requestID, 284 }, &core.MessageSendOptions{ 285 Receiver: node, 286 }, 287 ) 288 if err != nil { 289 return nil, err 290 } 291 292 switch r := genericReply.(type) { 293 case *reply.Request: 294 rec := record.DeserializeRecord(r.Record) 295 castedRecord, ok := rec.(*record.RequestRecord) 296 if !ok { 297 return nil, fmt.Errorf("GetPendingRequest: unexpected message: %#v", r) 298 } 299 300 return message.DeserializeParcel(bytes.NewBuffer(castedRecord.Parcel)) 301 case *reply.Error: 302 return nil, r.Error() 303 default: 304 return nil, fmt.Errorf("GetPendingRequest: unexpected reply: %#v", genericReply) 305 } 306 } 307 308 // HasPendingRequests returns true if object has unclosed requests. 309 func (m *LedgerArtifactManager) HasPendingRequests( 310 ctx context.Context, 311 object core.RecordRef, 312 ) (bool, error) { 313 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 314 sender := BuildSender( 315 bus.Send, 316 retryJetSender(m.JetStorage), 317 ) 318 319 genericReact, err := sender(ctx, &message.GetPendingRequests{Object: object}, nil) 320 321 if err != nil { 322 return false, err 323 } 324 325 switch rep := genericReact.(type) { 326 case *reply.HasPendingRequests: 327 return rep.Has, nil 328 case *reply.Error: 329 return false, rep.Error() 330 default: 331 return false, fmt.Errorf("HasPendingRequests: unexpected reply: %#v", rep) 332 } 333 } 334 335 // GetDelegate returns provided object's delegate reference for provided prototype. 336 // 337 // Object delegate should be previously created for this object. If object delegate does not exist, an error will 338 // be returned. 339 func (m *LedgerArtifactManager) GetDelegate( 340 ctx context.Context, head, asType core.RecordRef, 341 ) (*core.RecordRef, error) { 342 var err error 343 ctx, span := instracer.StartSpan(ctx, "artifactmanager.GetDelegate") 344 instrumenter := instrument(ctx, "GetDelegate").err(&err) 345 defer func() { 346 if err != nil { 347 span.AddAttributes(trace.StringAttribute("error", err.Error())) 348 } 349 span.End() 350 instrumenter.end() 351 }() 352 353 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 354 sender := BuildSender(bus.Send, followRedirectSender(bus), retryJetSender(m.JetStorage)) 355 genericReact, err := sender(ctx, &message.GetDelegate{ 356 Head: head, 357 AsType: asType, 358 }, nil) 359 if err != nil { 360 return nil, err 361 } 362 363 switch rep := genericReact.(type) { 364 case *reply.Delegate: 365 return &rep.Head, nil 366 case *reply.Error: 367 return nil, rep.Error() 368 default: 369 return nil, fmt.Errorf("GetDelegate: unexpected reply: %#v", rep) 370 } 371 } 372 373 // GetChildren returns children iterator. 374 // 375 // During iteration children refs will be fetched from remote source (parent object). 376 func (m *LedgerArtifactManager) GetChildren( 377 ctx context.Context, parent core.RecordRef, pulse *core.PulseNumber, 378 ) (core.RefIterator, error) { 379 var err error 380 381 ctx, span := instracer.StartSpan(ctx, "artifactmanager.GetChildren") 382 instrumenter := instrument(ctx, "GetChildren").err(&err) 383 defer func() { 384 if err != nil { 385 span.AddAttributes(trace.StringAttribute("error", err.Error())) 386 } 387 span.End() 388 instrumenter.end() 389 }() 390 391 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 392 sender := BuildSender(bus.Send, followRedirectSender(bus), retryJetSender(m.JetStorage)) 393 iter, err := NewChildIterator(ctx, sender, parent, pulse, m.getChildrenChunkSize) 394 return iter, err 395 } 396 397 // DeclareType creates new type record in storage. 398 // 399 // Type is a contract interface. It contains one method signature. 400 func (m *LedgerArtifactManager) DeclareType( 401 ctx context.Context, domain, request core.RecordRef, typeDec []byte, 402 ) (*core.RecordID, error) { 403 var err error 404 ctx, span := instracer.StartSpan(ctx, "artifactmanager.DeclareType") 405 instrumenter := instrument(ctx, "DeclareType").err(&err) 406 defer func() { 407 if err != nil { 408 span.AddAttributes(trace.StringAttribute("error", err.Error())) 409 } 410 span.End() 411 instrumenter.end() 412 }() 413 414 recid, err := m.setRecord( 415 ctx, 416 &record.TypeRecord{ 417 SideEffectRecord: record.SideEffectRecord{ 418 Domain: domain, 419 Request: request, 420 }, 421 TypeDeclaration: typeDec, 422 }, 423 request, 424 ) 425 return recid, err 426 } 427 428 // DeployCode creates new code record in storage. 429 // 430 // CodeRef records are used to activate prototype or as migration code for an object. 431 func (m *LedgerArtifactManager) DeployCode( 432 ctx context.Context, 433 domain core.RecordRef, 434 request core.RecordRef, 435 code []byte, 436 machineType core.MachineType, 437 ) (*core.RecordID, error) { 438 var err error 439 ctx, span := instracer.StartSpan(ctx, "artifactmanager.DeployCode") 440 instrumenter := instrument(ctx, "DeployCode").err(&err) 441 defer func() { 442 if err != nil { 443 span.AddAttributes(trace.StringAttribute("error", err.Error())) 444 } 445 span.End() 446 instrumenter.end() 447 }() 448 449 currentPN, err := m.pulse(ctx) 450 if err != nil { 451 return nil, err 452 } 453 454 codeRec := &record.CodeRecord{ 455 SideEffectRecord: record.SideEffectRecord{ 456 Domain: domain, 457 Request: request, 458 }, 459 Code: record.CalculateIDForBlob(m.PlatformCryptographyScheme, currentPN, code), 460 MachineType: machineType, 461 } 462 codeID := record.NewRecordIDFromRecord(m.PlatformCryptographyScheme, currentPN, codeRec) 463 codeRef := core.NewRecordRef(*domain.Record(), *codeID) 464 465 _, err = m.setBlob(ctx, code, *codeRef) 466 if err != nil { 467 return nil, err 468 } 469 id, err := m.setRecord( 470 ctx, 471 codeRec, 472 *codeRef, 473 ) 474 if err != nil { 475 return nil, err 476 } 477 478 return id, nil 479 } 480 481 // ActivatePrototype creates activate object record in storage. Provided prototype reference will be used as objects prototype 482 // memory as memory of created object. If memory is not provided, the prototype default memory will be used. 483 // 484 // Request reference will be this object's identifier and referred as "object head". 485 func (m *LedgerArtifactManager) ActivatePrototype( 486 ctx context.Context, 487 domain, object, parent, code core.RecordRef, 488 memory []byte, 489 ) (core.ObjectDescriptor, error) { 490 var err error 491 ctx, span := instracer.StartSpan(ctx, "artifactmanager.ActivatePrototype") 492 instrumenter := instrument(ctx, "ActivatePrototype").err(&err) 493 defer func() { 494 if err != nil { 495 span.AddAttributes(trace.StringAttribute("error", err.Error())) 496 } 497 span.End() 498 instrumenter.end() 499 }() 500 desc, err := m.activateObject(ctx, domain, object, code, true, parent, false, memory) 501 return desc, err 502 } 503 504 // ActivateObject creates activate object record in storage. Provided prototype reference will be used as objects prototype 505 // memory as memory of created object. If memory is not provided, the prototype default memory will be used. 506 // 507 // Request reference will be this object's identifier and referred as "object head". 508 func (m *LedgerArtifactManager) ActivateObject( 509 ctx context.Context, 510 domain, object, parent, prototype core.RecordRef, 511 asDelegate bool, 512 memory []byte, 513 ) (core.ObjectDescriptor, error) { 514 var err error 515 ctx, span := instracer.StartSpan(ctx, "artifactmanager.ActivateObject") 516 instrumenter := instrument(ctx, "ActivateObject").err(&err) 517 defer func() { 518 if err != nil { 519 span.AddAttributes(trace.StringAttribute("error", err.Error())) 520 } 521 span.End() 522 instrumenter.end() 523 }() 524 desc, err := m.activateObject(ctx, domain, object, prototype, false, parent, asDelegate, memory) 525 return desc, err 526 } 527 528 // DeactivateObject creates deactivate object record in storage. Provided reference should be a reference to the head 529 // of the object. If object is already deactivated, an error should be returned. 530 // 531 // Deactivated object cannot be changed. 532 func (m *LedgerArtifactManager) DeactivateObject( 533 ctx context.Context, domain, request core.RecordRef, object core.ObjectDescriptor, 534 ) (*core.RecordID, error) { 535 var err error 536 ctx, span := instracer.StartSpan(ctx, "artifactmanager.DeactivateObject") 537 instrumenter := instrument(ctx, "DeactivateObject").err(&err) 538 defer func() { 539 if err != nil { 540 span.AddAttributes(trace.StringAttribute("error", err.Error())) 541 } 542 span.End() 543 instrumenter.end() 544 }() 545 546 desc, err := m.sendUpdateObject( 547 ctx, 548 &record.DeactivationRecord{ 549 SideEffectRecord: record.SideEffectRecord{ 550 Domain: domain, 551 Request: request, 552 }, 553 PrevState: *object.StateID(), 554 }, 555 *object.HeadRef(), 556 nil, 557 ) 558 if err != nil { 559 return nil, errors.Wrap(err, "failed to deactivate object") 560 } 561 return &desc.State, nil 562 } 563 564 // UpdatePrototype creates amend object record in storage. Provided reference should be a reference to the head of the 565 // prototype. Provided memory well be the new object memory. 566 // 567 // Returned reference will be the latest object state (exact) reference. 568 func (m *LedgerArtifactManager) UpdatePrototype( 569 ctx context.Context, 570 domain, request core.RecordRef, 571 object core.ObjectDescriptor, 572 memory []byte, 573 code *core.RecordRef, 574 ) (core.ObjectDescriptor, error) { 575 var err error 576 ctx, span := instracer.StartSpan(ctx, "artifactmanager.UpdatePrototype") 577 instrumenter := instrument(ctx, "UpdatePrototype").err(&err) 578 defer func() { 579 if err != nil { 580 span.AddAttributes(trace.StringAttribute("error", err.Error())) 581 } 582 span.End() 583 instrumenter.end() 584 }() 585 586 if !object.IsPrototype() { 587 err = errors.New("object is not a prototype") 588 return nil, err 589 } 590 desc, err := m.updateObject(ctx, domain, request, object, code, memory) 591 return desc, err 592 } 593 594 // UpdateObject creates amend object record in storage. Provided reference should be a reference to the head of the 595 // object. Provided memory well be the new object memory. 596 // 597 // Returned reference will be the latest object state (exact) reference. 598 func (m *LedgerArtifactManager) UpdateObject( 599 ctx context.Context, 600 domain, request core.RecordRef, 601 object core.ObjectDescriptor, 602 memory []byte, 603 ) (core.ObjectDescriptor, error) { 604 var err error 605 ctx, span := instracer.StartSpan(ctx, "artifactmanager.UpdateObject") 606 instrumenter := instrument(ctx, "UpdateObject").err(&err) 607 defer func() { 608 if err != nil { 609 span.AddAttributes(trace.StringAttribute("error", err.Error())) 610 } 611 span.End() 612 instrumenter.end() 613 }() 614 615 if object.IsPrototype() { 616 err = errors.New("object is not an instance") 617 return nil, err 618 } 619 desc, err := m.updateObject(ctx, domain, request, object, nil, memory) 620 return desc, err 621 } 622 623 // RegisterValidation marks provided object state as approved or disapproved. 624 // 625 // When fetching object, validity can be specified. 626 func (m *LedgerArtifactManager) RegisterValidation( 627 ctx context.Context, 628 object core.RecordRef, 629 state core.RecordID, 630 isValid bool, 631 validationMessages []core.Message, 632 ) error { 633 var err error 634 ctx, span := instracer.StartSpan(ctx, "artifactmanager.RegisterValidation") 635 instrumenter := instrument(ctx, "RegisterValidation").err(&err) 636 defer func() { 637 if err != nil { 638 span.AddAttributes(trace.StringAttribute("error", err.Error())) 639 } 640 span.End() 641 instrumenter.end() 642 }() 643 644 msg := message.ValidateRecord{ 645 Object: object, 646 State: state, 647 IsValid: isValid, 648 ValidationMessages: validationMessages, 649 } 650 651 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 652 sender := BuildSender(bus.Send, retryJetSender(m.JetStorage)) 653 _, err = sender(ctx, &msg, nil) 654 655 return err 656 } 657 658 // RegisterResult saves VM method call result. 659 func (m *LedgerArtifactManager) RegisterResult( 660 ctx context.Context, object, request core.RecordRef, payload []byte, 661 ) (*core.RecordID, error) { 662 var err error 663 ctx, span := instracer.StartSpan(ctx, "artifactmanager.RegisterResult") 664 instrumenter := instrument(ctx, "RegisterResult").err(&err) 665 defer func() { 666 if err != nil { 667 span.AddAttributes(trace.StringAttribute("error", err.Error())) 668 } 669 span.End() 670 instrumenter.end() 671 }() 672 673 recid, err := m.setRecord( 674 ctx, 675 &record.ResultRecord{ 676 Object: *object.Record(), 677 Request: request, 678 Payload: payload, 679 }, 680 request, 681 ) 682 return recid, err 683 } 684 685 // pulse returns current PulseNumber for artifact manager 686 func (m *LedgerArtifactManager) pulse(ctx context.Context) (pn core.PulseNumber, err error) { 687 pulse, err := m.PulseStorage.Current(ctx) 688 if err != nil { 689 return 690 } 691 692 pn = pulse.PulseNumber 693 return 694 } 695 696 func (m *LedgerArtifactManager) activateObject( 697 ctx context.Context, 698 domain core.RecordRef, 699 object core.RecordRef, 700 prototype core.RecordRef, 701 isPrototype bool, 702 parent core.RecordRef, 703 asDelegate bool, 704 memory []byte, 705 ) (core.ObjectDescriptor, error) { 706 parentDesc, err := m.GetObject(ctx, parent, nil, false) 707 if err != nil { 708 return nil, err 709 } 710 currentPN, err := m.pulse(ctx) 711 if err != nil { 712 return nil, err 713 } 714 715 obj, err := m.sendUpdateObject( 716 ctx, 717 &record.ObjectActivateRecord{ 718 SideEffectRecord: record.SideEffectRecord{ 719 Domain: domain, 720 Request: object, 721 }, 722 ObjectStateRecord: record.ObjectStateRecord{ 723 Memory: record.CalculateIDForBlob(m.PlatformCryptographyScheme, currentPN, memory), 724 Image: prototype, 725 IsPrototype: isPrototype, 726 }, 727 Parent: parent, 728 IsDelegate: asDelegate, 729 }, 730 object, 731 memory, 732 ) 733 if err != nil { 734 return nil, errors.Wrap(err, "failed to activate") 735 } 736 737 var ( 738 prevChild *core.RecordID 739 asType *core.RecordRef 740 ) 741 if parentDesc.ChildPointer() != nil { 742 prevChild = parentDesc.ChildPointer() 743 } 744 if asDelegate { 745 asType = &prototype 746 } 747 _, err = m.registerChild( 748 ctx, 749 &record.ChildRecord{ 750 Ref: object, 751 PrevChild: prevChild, 752 }, 753 parent, 754 object, 755 asType, 756 ) 757 if err != nil { 758 return nil, errors.Wrap(err, "failed to register as child while activating") 759 } 760 761 return &ObjectDescriptor{ 762 ctx: ctx, 763 am: m, 764 head: obj.Head, 765 state: obj.State, 766 prototype: obj.Prototype, 767 childPointer: obj.ChildPointer, 768 memory: memory, 769 parent: obj.Parent, 770 }, nil 771 } 772 773 func (m *LedgerArtifactManager) updateObject( 774 ctx context.Context, 775 domain, request core.RecordRef, 776 object core.ObjectDescriptor, 777 code *core.RecordRef, 778 memory []byte, 779 ) (core.ObjectDescriptor, error) { 780 var ( 781 image *core.RecordRef 782 err error 783 ) 784 if object.IsPrototype() { 785 if code != nil { 786 image = code 787 } else { 788 image, err = object.Code() 789 } 790 } else { 791 image, err = object.Prototype() 792 } 793 if err != nil { 794 return nil, errors.Wrap(err, "failed to update object") 795 } 796 797 obj, err := m.sendUpdateObject( 798 ctx, 799 &record.ObjectAmendRecord{ 800 SideEffectRecord: record.SideEffectRecord{ 801 Domain: domain, 802 Request: request, 803 }, 804 ObjectStateRecord: record.ObjectStateRecord{ 805 Image: *image, 806 IsPrototype: object.IsPrototype(), 807 }, 808 PrevState: *object.StateID(), 809 }, 810 *object.HeadRef(), 811 memory, 812 ) 813 if err != nil { 814 return nil, errors.Wrap(err, "failed to update object") 815 } 816 817 return &ObjectDescriptor{ 818 ctx: ctx, 819 am: m, 820 head: obj.Head, 821 state: obj.State, 822 prototype: obj.Prototype, 823 childPointer: obj.ChildPointer, 824 memory: memory, 825 parent: obj.Parent, 826 }, nil 827 } 828 829 func (m *LedgerArtifactManager) setRecord( 830 ctx context.Context, 831 rec record.Record, 832 target core.RecordRef, 833 ) (*core.RecordID, error) { 834 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 835 836 sender := BuildSender(bus.Send, retryJetSender(m.JetStorage)) 837 genericReply, err := sender(ctx, &message.SetRecord{ 838 Record: record.SerializeRecord(rec), 839 TargetRef: target, 840 }, nil) 841 842 if err != nil { 843 return nil, err 844 } 845 846 switch rep := genericReply.(type) { 847 case *reply.ID: 848 return &rep.ID, nil 849 case *reply.Error: 850 return nil, rep.Error() 851 default: 852 return nil, fmt.Errorf("setRecord: unexpected reply: %#v", rep) 853 } 854 } 855 856 func (m *LedgerArtifactManager) setBlob( 857 ctx context.Context, 858 blob []byte, 859 target core.RecordRef, 860 ) (*core.RecordID, error) { 861 862 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 863 sender := BuildSender(bus.Send, retryJetSender(m.JetStorage)) 864 genericReact, err := sender(ctx, &message.SetBlob{ 865 Memory: blob, 866 TargetRef: target, 867 }, nil) 868 869 if err != nil { 870 return nil, err 871 } 872 873 switch rep := genericReact.(type) { 874 case *reply.ID: 875 return &rep.ID, nil 876 case *reply.Error: 877 return nil, rep.Error() 878 default: 879 return nil, fmt.Errorf("setBlob: unexpected reply: %#v", rep) 880 } 881 } 882 883 func (m *LedgerArtifactManager) sendUpdateObject( 884 ctx context.Context, 885 rec record.Record, 886 object core.RecordRef, 887 memory []byte, 888 ) (*reply.Object, error) { 889 // TODO: @andreyromancev. 14.01.19. Uncomment when message streaming or validation is ready. 890 // genericRep, err := sendAndRetryJet(ctx, m.bus(ctx), m.db, &message.SetBlob{ 891 // TargetRef: object, 892 // Memory: memory, 893 // }, currentPulse, jetMissRetryCount, nil) 894 // if err != nil { 895 // return nil, errors.Wrap(err, "failed to save object's memory blob") 896 // } 897 // if _, ok := genericRep.(*reply.ID); !ok { 898 // return nil, fmt.Errorf("unexpected reply: %#v\n", genericRep) 899 // } 900 901 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 902 sender := BuildSender(bus.Send, retryJetSender(m.JetStorage)) 903 genericReply, err := sender( 904 ctx, 905 &message.UpdateObject{ 906 Record: record.SerializeRecord(rec), 907 Object: object, 908 Memory: memory, 909 }, nil) 910 911 if err != nil { 912 return nil, errors.Wrap(err, "UpdateObject message failed") 913 } 914 915 switch rep := genericReply.(type) { 916 case *reply.Object: 917 return rep, nil 918 case *reply.Error: 919 return nil, rep.Error() 920 default: 921 return nil, fmt.Errorf("sendUpdateObject: unexpected reply: %#v", rep) 922 } 923 } 924 925 func (m *LedgerArtifactManager) registerChild( 926 ctx context.Context, 927 rec record.Record, 928 parent core.RecordRef, 929 child core.RecordRef, 930 asType *core.RecordRef, 931 ) (*core.RecordID, error) { 932 bus := core.MessageBusFromContext(ctx, m.DefaultBus) 933 sender := BuildSender(bus.Send, retryJetSender(m.JetStorage)) 934 genericReact, err := sender(ctx, &message.RegisterChild{ 935 Record: record.SerializeRecord(rec), 936 Parent: parent, 937 Child: child, 938 AsType: asType, 939 }, nil) 940 941 if err != nil { 942 return nil, err 943 } 944 945 switch rep := genericReact.(type) { 946 case *reply.ID: 947 return &rep.ID, nil 948 case *reply.Error: 949 return nil, rep.Error() 950 default: 951 return nil, fmt.Errorf("registerChild: unexpected reply: %#v", rep) 952 } 953 }