github.com/braveheart12/just@v0.8.7/ledger/artifactmanager/artifactmanager_test.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  	"context"
    21  	"math/rand"
    22  	"testing"
    23  
    24  	"github.com/gojuno/minimock"
    25  	"github.com/insolar/insolar/ledger/storage/nodes"
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/require"
    28  	"github.com/stretchr/testify/suite"
    29  
    30  	"github.com/insolar/insolar/component"
    31  	"github.com/insolar/insolar/configuration"
    32  	"github.com/insolar/insolar/core"
    33  	"github.com/insolar/insolar/core/delegationtoken"
    34  	"github.com/insolar/insolar/core/message"
    35  	"github.com/insolar/insolar/core/reply"
    36  	"github.com/insolar/insolar/instrumentation/inslogger"
    37  	"github.com/insolar/insolar/ledger/recentstorage"
    38  	"github.com/insolar/insolar/ledger/storage"
    39  	"github.com/insolar/insolar/ledger/storage/index"
    40  	"github.com/insolar/insolar/ledger/storage/jet"
    41  	"github.com/insolar/insolar/ledger/storage/record"
    42  	"github.com/insolar/insolar/ledger/storage/storagetest"
    43  	"github.com/insolar/insolar/platformpolicy"
    44  	"github.com/insolar/insolar/testutils"
    45  	"github.com/insolar/insolar/testutils/testmessagebus"
    46  )
    47  
    48  type amSuite struct {
    49  	suite.Suite
    50  
    51  	cm      *component.Manager
    52  	ctx     context.Context
    53  	cleaner func()
    54  	db      storage.DBContext
    55  
    56  	scheme        core.PlatformCryptographyScheme
    57  	pulseTracker  storage.PulseTracker
    58  	nodeStorage   nodes.Accessor
    59  	objectStorage storage.ObjectStorage
    60  	jetStorage    storage.JetStorage
    61  	dropStorage   storage.DropStorage
    62  	genesisState  storage.GenesisState
    63  }
    64  
    65  func NewAmSuite() *amSuite {
    66  	return &amSuite{
    67  		Suite: suite.Suite{},
    68  	}
    69  }
    70  
    71  // Init and run suite
    72  func TestArtifactManager(t *testing.T) {
    73  	suite.Run(t, NewAmSuite())
    74  }
    75  
    76  func (s *amSuite) BeforeTest(suiteName, testName string) {
    77  	s.cm = &component.Manager{}
    78  	s.ctx = inslogger.TestContext(s.T())
    79  
    80  	db, cleaner := storagetest.TmpDB(s.ctx, s.T())
    81  	s.cleaner = cleaner
    82  	s.db = db
    83  	s.scheme = platformpolicy.NewPlatformCryptographyScheme()
    84  	s.jetStorage = storage.NewJetStorage()
    85  	s.nodeStorage = nodes.NewStorage()
    86  	s.pulseTracker = storage.NewPulseTracker()
    87  	s.objectStorage = storage.NewObjectStorage()
    88  	s.dropStorage = storage.NewDropStorage(10)
    89  	s.genesisState = storage.NewGenesisInitializer()
    90  
    91  	s.cm.Inject(
    92  		s.scheme,
    93  		s.db,
    94  		s.jetStorage,
    95  		s.nodeStorage,
    96  		s.pulseTracker,
    97  		s.objectStorage,
    98  		s.dropStorage,
    99  		s.genesisState,
   100  	)
   101  
   102  	err := s.cm.Init(s.ctx)
   103  	if err != nil {
   104  		s.T().Error("ComponentManager init failed", err)
   105  	}
   106  	err = s.cm.Start(s.ctx)
   107  	if err != nil {
   108  		s.T().Error("ComponentManager start failed", err)
   109  	}
   110  }
   111  
   112  func (s *amSuite) AfterTest(suiteName, testName string) {
   113  	err := s.cm.Stop(s.ctx)
   114  	if err != nil {
   115  		s.T().Error("ComponentManager stop failed", err)
   116  	}
   117  	s.cleaner()
   118  }
   119  
   120  var (
   121  	domainID   = *genRandomID(0)
   122  	domainRef  = *core.NewRecordRef(domainID, domainID)
   123  	requestRef = *genRandomRef(0)
   124  )
   125  
   126  func genRandomID(pulse core.PulseNumber) *core.RecordID {
   127  	buff := [core.RecordIDSize - core.PulseNumberSize]byte{}
   128  	_, err := rand.Read(buff[:])
   129  	if err != nil {
   130  		panic(err)
   131  	}
   132  	return core.NewRecordID(pulse, buff[:])
   133  }
   134  
   135  func genRefWithID(id *core.RecordID) *core.RecordRef {
   136  	return core.NewRecordRef(domainID, *id)
   137  }
   138  
   139  func genRandomRef(pulse core.PulseNumber) *core.RecordRef {
   140  	return genRefWithID(genRandomID(pulse))
   141  }
   142  
   143  func getTestData(s *amSuite) (
   144  	context.Context,
   145  	storage.ObjectStorage,
   146  	*LedgerArtifactManager,
   147  ) {
   148  	mc := minimock.NewController(s.T())
   149  	pulseStorage := storage.NewPulseStorage()
   150  	pulseStorage.PulseTracker = s.pulseTracker
   151  
   152  	pulse, err := s.pulseTracker.GetLatestPulse(s.ctx)
   153  	require.NoError(s.T(), err)
   154  	pulseStorage.Set(&pulse.Pulse)
   155  
   156  	mb := testmessagebus.NewTestMessageBus(s.T())
   157  	mb.PulseStorage = pulseStorage
   158  
   159  	certificate := testutils.NewCertificateMock(s.T())
   160  	certificate.GetRoleMock.Return(core.StaticRoleLightMaterial)
   161  
   162  	handler := MessageHandler{
   163  		replayHandlers:             map[core.MessageType]core.MessageHandler{},
   164  		PlatformCryptographyScheme: s.scheme,
   165  		conf:        &configuration.Ledger{LightChainLimit: 3, PendingRequestsLimit: 10},
   166  		certificate: certificate,
   167  	}
   168  
   169  	handler.Nodes = s.nodeStorage
   170  	handler.ObjectStorage = s.objectStorage
   171  	handler.PulseTracker = s.pulseTracker
   172  	handler.DBContext = s.db
   173  	handler.JetStorage = s.jetStorage
   174  
   175  	indexMock := recentstorage.NewRecentIndexStorageMock(s.T())
   176  	pendingMock := recentstorage.NewPendingStorageMock(s.T())
   177  
   178  	indexMock.AddObjectMock.Return()
   179  	pendingMock.GetRequestsForObjectMock.Return(nil)
   180  	pendingMock.AddPendingRequestMock.Return()
   181  	pendingMock.RemovePendingRequestMock.Return()
   182  
   183  	provideMock := recentstorage.NewProviderMock(s.T())
   184  	provideMock.GetIndexStorageMock.Return(indexMock)
   185  	provideMock.GetPendingStorageMock.Return(pendingMock)
   186  	provideMock.CountMock.Return(1)
   187  
   188  	handler.RecentStorageProvider = provideMock
   189  
   190  	handler.Bus = mb
   191  
   192  	jc := testutils.NewJetCoordinatorMock(mc)
   193  	jc.LightExecutorForJetMock.Return(&core.RecordRef{}, nil)
   194  	jc.MeMock.Return(core.RecordRef{})
   195  	jc.HeavyMock.Return(&core.RecordRef{}, nil)
   196  	jc.NodeForJetMock.Return(&core.RecordRef{}, nil)
   197  	jc.IsBeyondLimitMock.Return(false, nil)
   198  
   199  	handler.JetCoordinator = jc
   200  
   201  	err = handler.Init(s.ctx)
   202  	require.NoError(s.T(), err)
   203  
   204  	am := LedgerArtifactManager{
   205  		DB:                         s.db,
   206  		DefaultBus:                 mb,
   207  		getChildrenChunkSize:       100,
   208  		PlatformCryptographyScheme: s.scheme,
   209  		PulseStorage:               pulseStorage,
   210  		GenesisState:               s.genesisState,
   211  	}
   212  
   213  	return s.ctx, s.objectStorage, &am
   214  }
   215  
   216  func (s *amSuite) TestLedgerArtifactManager_RegisterRequest() {
   217  	ctx, os, am := getTestData(s)
   218  
   219  	parcel := message.Parcel{Msg: &message.GenesisRequest{Name: "4K3NiGuqYGqKPnYp6XeGd2kdN4P9veL6rYcWkLKWXZCu.4FFB8zfQoGznSmzDxwv4njX1aR9ioL8GHSH17QXH2AFa"}}
   220  	id, err := am.RegisterRequest(ctx, *am.GenesisRef(), &parcel)
   221  	assert.NoError(s.T(), err)
   222  	rec, err := os.GetRecord(ctx, *jet.NewID(0, nil), id)
   223  	assert.NoError(s.T(), err)
   224  
   225  	assert.Equal(
   226  		s.T(),
   227  		am.PlatformCryptographyScheme.IntegrityHasher().Hash(message.MustSerializeBytes(parcel.Msg)),
   228  		rec.(*record.RequestRecord).MessageHash,
   229  	)
   230  }
   231  
   232  func (s *amSuite) TestLedgerArtifactManager_GetCodeWithCache() {
   233  	code := []byte("test_code")
   234  	codeRef := testutils.RandomRef()
   235  
   236  	mb := testutils.NewMessageBusMock(s.T())
   237  	mb.SendFunc = func(p context.Context, p1 core.Message, p3 *core.MessageSendOptions) (r core.Reply, r1 error) {
   238  		return &reply.Code{
   239  			Code: code,
   240  		}, nil
   241  	}
   242  
   243  	jc := testutils.NewJetCoordinatorMock(s.T())
   244  	jc.LightExecutorForJetMock.Return(&core.RecordRef{}, nil)
   245  	jc.MeMock.Return(core.RecordRef{})
   246  
   247  	amPulseStorageMock := testutils.NewPulseStorageMock(s.T())
   248  	amPulseStorageMock.CurrentFunc = func(p context.Context) (r *core.Pulse, r1 error) {
   249  		pulse, err := s.pulseTracker.GetLatestPulse(p)
   250  		require.NoError(s.T(), err)
   251  		return &pulse.Pulse, err
   252  	}
   253  
   254  	am := LedgerArtifactManager{
   255  		DefaultBus:                 mb,
   256  		DB:                         s.db,
   257  		PulseStorage:               amPulseStorageMock,
   258  		JetCoordinator:             jc,
   259  		PlatformCryptographyScheme: s.scheme,
   260  		senders:                    newLedgerArtifactSenders(),
   261  	}
   262  
   263  	desc, err := am.GetCode(s.ctx, codeRef)
   264  	receivedCode, err := desc.Code()
   265  	require.NoError(s.T(), err)
   266  	require.Equal(s.T(), code, receivedCode)
   267  
   268  	mb.SendFunc = func(p context.Context, p1 core.Message, p3 *core.MessageSendOptions) (r core.Reply, r1 error) {
   269  		s.T().Fatal("Func must not be called here")
   270  		return nil, nil
   271  	}
   272  
   273  	desc, err = am.GetCode(s.ctx, codeRef)
   274  	receivedCode, err = desc.Code()
   275  	require.NoError(s.T(), err)
   276  	require.Equal(s.T(), code, receivedCode)
   277  
   278  }
   279  
   280  func (s *amSuite) TestLedgerArtifactManager_DeclareType() {
   281  	ctx, os, am := getTestData(s)
   282  
   283  	typeDec := []byte{1, 2, 3}
   284  	id, err := am.DeclareType(ctx, domainRef, requestRef, typeDec)
   285  	assert.NoError(s.T(), err)
   286  	typeRec, err := os.GetRecord(ctx, *jet.NewID(0, nil), id)
   287  	assert.NoError(s.T(), err)
   288  	assert.Equal(s.T(), &record.TypeRecord{
   289  		SideEffectRecord: record.SideEffectRecord{
   290  			Domain:  domainRef,
   291  			Request: requestRef,
   292  		},
   293  		TypeDeclaration: typeDec,
   294  	}, typeRec)
   295  }
   296  
   297  func (s *amSuite) TestLedgerArtifactManager_DeployCode_CreatesCorrectRecord() {
   298  	ctx, os, am := getTestData(s)
   299  
   300  	id, err := am.DeployCode(
   301  		ctx,
   302  		domainRef,
   303  		requestRef,
   304  		[]byte{1, 2, 3},
   305  		core.MachineTypeBuiltin,
   306  	)
   307  	assert.NoError(s.T(), err)
   308  	codeRec, err := os.GetRecord(ctx, *jet.NewID(0, nil), id)
   309  	assert.NoError(s.T(), err)
   310  	assert.Equal(s.T(), codeRec, &record.CodeRecord{
   311  		SideEffectRecord: record.SideEffectRecord{
   312  			Domain:  domainRef,
   313  			Request: requestRef,
   314  		},
   315  		Code:        record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{1, 2, 3}),
   316  		MachineType: core.MachineTypeBuiltin,
   317  	})
   318  }
   319  
   320  func (s *amSuite) TestLedgerArtifactManager_ActivateObject_CreatesCorrectRecord() {
   321  	ctx, os, am := getTestData(s)
   322  	jetID := *jet.NewID(0, nil)
   323  
   324  	memory := []byte{1, 2, 3}
   325  	codeRef := genRandomRef(0)
   326  	parentID, _ := os.SetRecord(
   327  		ctx,
   328  		jetID,
   329  		core.GenesisPulse.PulseNumber,
   330  		&record.ObjectActivateRecord{
   331  			SideEffectRecord: record.SideEffectRecord{
   332  				Domain: *genRandomRef(0),
   333  			},
   334  		},
   335  	)
   336  	err := os.SetObjectIndex(ctx, jetID, parentID, &index.ObjectLifeline{
   337  		LatestState: parentID,
   338  	})
   339  	require.NoError(s.T(), err)
   340  
   341  	objRef := *genRandomRef(0)
   342  	objDesc, err := am.ActivateObject(
   343  		ctx,
   344  		domainRef,
   345  		objRef,
   346  		*genRefWithID(parentID),
   347  		*codeRef,
   348  		false,
   349  		memory,
   350  	)
   351  	assert.Nil(s.T(), err)
   352  	activateRec, err := os.GetRecord(ctx, jetID, objDesc.StateID())
   353  	assert.Nil(s.T(), err)
   354  	assert.Equal(s.T(), activateRec, &record.ObjectActivateRecord{
   355  		SideEffectRecord: record.SideEffectRecord{
   356  			Domain:  domainRef,
   357  			Request: objRef,
   358  		},
   359  		ObjectStateRecord: record.ObjectStateRecord{
   360  			Memory:      record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, memory),
   361  			Image:       *codeRef,
   362  			IsPrototype: false,
   363  		},
   364  		Parent:     *genRefWithID(parentID),
   365  		IsDelegate: false,
   366  	})
   367  
   368  	idx, err := os.GetObjectIndex(ctx, jetID, parentID, false)
   369  	assert.NoError(s.T(), err)
   370  	childRec, err := os.GetRecord(ctx, jetID, idx.ChildPointer)
   371  	assert.NoError(s.T(), err)
   372  	assert.Equal(s.T(), objRef, childRec.(*record.ChildRecord).Ref)
   373  
   374  	idx, err = os.GetObjectIndex(ctx, jetID, objRef.Record(), false)
   375  	assert.NoError(s.T(), err)
   376  	assert.Equal(s.T(), *objDesc.StateID(), *idx.LatestState)
   377  	assert.Equal(s.T(), *objDesc.Parent(), idx.Parent)
   378  }
   379  
   380  func (s *amSuite) TestLedgerArtifactManager_DeactivateObject_CreatesCorrectRecord() {
   381  	ctx, os, am := getTestData(s)
   382  	jetID := *jet.NewID(0, nil)
   383  
   384  	objID, _ := os.SetRecord(
   385  		ctx,
   386  		jetID,
   387  		core.GenesisPulse.PulseNumber,
   388  		&record.ObjectActivateRecord{
   389  			SideEffectRecord: record.SideEffectRecord{
   390  				Domain: *genRandomRef(0),
   391  			},
   392  		},
   393  	)
   394  	err := os.SetObjectIndex(ctx, jetID, objID, &index.ObjectLifeline{
   395  		State:       record.StateActivation,
   396  		LatestState: objID,
   397  	})
   398  	require.NoError(s.T(), err)
   399  	deactivateID, err := am.DeactivateObject(
   400  		ctx,
   401  		domainRef,
   402  		requestRef,
   403  		&ObjectDescriptor{
   404  			ctx:   ctx,
   405  			head:  *genRefWithID(objID),
   406  			state: *objID,
   407  		},
   408  	)
   409  	assert.Nil(s.T(), err)
   410  	deactivateRec, err := os.GetRecord(ctx, jetID, deactivateID)
   411  	assert.Nil(s.T(), err)
   412  	assert.Equal(s.T(), deactivateRec, &record.DeactivationRecord{
   413  		SideEffectRecord: record.SideEffectRecord{
   414  			Domain:  domainRef,
   415  			Request: requestRef,
   416  		},
   417  		PrevState: *objID,
   418  	})
   419  }
   420  
   421  func (s *amSuite) TestLedgerArtifactManager_UpdateObject_CreatesCorrectRecord() {
   422  	ctx, os, am := getTestData(s)
   423  	jetID := *jet.NewID(0, nil)
   424  
   425  	objID, _ := os.SetRecord(
   426  		ctx,
   427  		jetID,
   428  		core.GenesisPulse.PulseNumber,
   429  		&record.ObjectActivateRecord{
   430  			SideEffectRecord: record.SideEffectRecord{
   431  				Domain: *genRandomRef(0),
   432  			},
   433  		},
   434  	)
   435  	err := os.SetObjectIndex(ctx, jetID, objID, &index.ObjectLifeline{
   436  		State:       record.StateActivation,
   437  		LatestState: objID,
   438  	})
   439  	require.NoError(s.T(), err)
   440  	memory := []byte{1, 2, 3}
   441  	prototype := genRandomRef(0)
   442  	obj, err := am.UpdateObject(
   443  		ctx,
   444  		domainRef,
   445  		requestRef,
   446  		&ObjectDescriptor{
   447  			ctx:       ctx,
   448  			head:      *genRefWithID(objID),
   449  			state:     *objID,
   450  			prototype: prototype,
   451  		},
   452  		memory,
   453  	)
   454  	assert.Nil(s.T(), err)
   455  	updateRec, err := os.GetRecord(ctx, jetID, obj.StateID())
   456  	assert.Nil(s.T(), err)
   457  	assert.Equal(s.T(), updateRec, &record.ObjectAmendRecord{
   458  		SideEffectRecord: record.SideEffectRecord{
   459  			Domain:  domainRef,
   460  			Request: requestRef,
   461  		},
   462  		ObjectStateRecord: record.ObjectStateRecord{
   463  			Memory:      record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, memory),
   464  			Image:       *prototype,
   465  			IsPrototype: false,
   466  		},
   467  		PrevState: *objID,
   468  	})
   469  }
   470  
   471  func (s *amSuite) TestLedgerArtifactManager_GetObject_ReturnsCorrectDescriptors() {
   472  	ctx, os, am := getTestData(s)
   473  	jetID := *jet.NewID(0, nil)
   474  
   475  	prototypeRef := genRandomRef(0)
   476  	parentRef := genRandomRef(0)
   477  	objRef := genRandomRef(0)
   478  	_, err := os.SetRecord(
   479  		ctx,
   480  		jetID,
   481  		core.GenesisPulse.PulseNumber,
   482  		&record.ObjectActivateRecord{
   483  			SideEffectRecord: record.SideEffectRecord{
   484  				Domain: domainRef,
   485  			},
   486  			ObjectStateRecord: record.ObjectStateRecord{
   487  				Memory: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{3}),
   488  			},
   489  			Parent: *parentRef,
   490  		},
   491  	)
   492  	require.NoError(s.T(), err)
   493  	_, err = os.SetBlob(ctx, jetID, core.GenesisPulse.PulseNumber, []byte{3})
   494  	require.NoError(s.T(), err)
   495  	objectAmendID, _ := os.SetRecord(ctx, jetID, core.GenesisPulse.PulseNumber, &record.ObjectAmendRecord{
   496  		SideEffectRecord: record.SideEffectRecord{
   497  			Domain: domainRef,
   498  		},
   499  		ObjectStateRecord: record.ObjectStateRecord{
   500  			Memory: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{4}),
   501  			Image:  *prototypeRef,
   502  		},
   503  	})
   504  	_, err = os.SetBlob(ctx, jetID, core.GenesisPulse.PulseNumber, []byte{4})
   505  	require.NoError(s.T(), err)
   506  
   507  	objectIndex := index.ObjectLifeline{
   508  		LatestState:  objectAmendID,
   509  		ChildPointer: genRandomID(0),
   510  		Parent:       *parentRef,
   511  	}
   512  	require.NoError(
   513  		s.T(),
   514  		os.SetObjectIndex(ctx, jetID, objRef.Record(), &objectIndex),
   515  	)
   516  
   517  	objDesc, err := am.GetObject(ctx, *objRef, nil, false)
   518  	rObjDesc := objDesc.(*ObjectDescriptor)
   519  	assert.NoError(s.T(), err)
   520  	expectedObjDesc := &ObjectDescriptor{
   521  		ctx:          rObjDesc.ctx,
   522  		am:           am,
   523  		head:         *objRef,
   524  		state:        *objectAmendID,
   525  		prototype:    prototypeRef,
   526  		isPrototype:  false,
   527  		childPointer: objectIndex.ChildPointer,
   528  		memory:       []byte{4},
   529  		parent:       *parentRef,
   530  	}
   531  	assert.Equal(s.T(), *expectedObjDesc, *rObjDesc)
   532  }
   533  
   534  func (s *amSuite) TestLedgerArtifactManager_GetObject_FollowsRedirect() {
   535  	mc := minimock.NewController(s.T())
   536  	am := NewArtifactManger()
   537  	mb := testutils.NewMessageBusMock(mc)
   538  
   539  	objRef := genRandomRef(0)
   540  	nodeRef := genRandomRef(0)
   541  	mb.SendFunc = func(c context.Context, m core.Message, o *core.MessageSendOptions) (r core.Reply, r1 error) {
   542  		o = o.Safe()
   543  
   544  		switch m.(type) {
   545  		case *message.GetObjectIndex:
   546  			return &reply.ObjectIndex{}, nil
   547  		case *message.GetObject:
   548  			if o.Receiver == nil {
   549  				return &reply.GetObjectRedirectReply{
   550  					Receiver: nodeRef,
   551  					Token:    &delegationtoken.GetObjectRedirectToken{Signature: []byte{1, 2, 3}},
   552  				}, nil
   553  			}
   554  
   555  			token, ok := o.Token.(*delegationtoken.GetObjectRedirectToken)
   556  			assert.True(s.T(), ok)
   557  			assert.Equal(s.T(), []byte{1, 2, 3}, token.Signature)
   558  			assert.Equal(s.T(), nodeRef, o.Receiver)
   559  			return &reply.Object{}, nil
   560  		default:
   561  			panic("unexpected call")
   562  		}
   563  	}
   564  	am.DefaultBus = mb
   565  	am.DB = s.db
   566  	am.PulseStorage = makePulseStorage(s)
   567  
   568  	_, err := am.GetObject(s.ctx, *objRef, nil, false)
   569  
   570  	require.NoError(s.T(), err)
   571  }
   572  
   573  func (s *amSuite) TestLedgerArtifactManager_GetChildren() {
   574  	// t.Parallel()
   575  	ctx, os, am := getTestData(s)
   576  	// defer cleaner()
   577  	jetID := *jet.NewID(0, nil)
   578  
   579  	parentID, _ := os.SetRecord(
   580  		ctx,
   581  		jetID,
   582  		core.GenesisPulse.PulseNumber,
   583  		&record.ObjectActivateRecord{
   584  			SideEffectRecord: record.SideEffectRecord{
   585  				Domain: domainRef,
   586  			},
   587  			ObjectStateRecord: record.ObjectStateRecord{
   588  				Memory: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{0}),
   589  			},
   590  		})
   591  	child1Ref := genRandomRef(1)
   592  	child2Ref := genRandomRef(1)
   593  	child3Ref := genRandomRef(2)
   594  
   595  	childMeta1, _ := os.SetRecord(
   596  		ctx,
   597  		jetID,
   598  		core.GenesisPulse.PulseNumber,
   599  		&record.ChildRecord{
   600  			Ref: *child1Ref,
   601  		})
   602  	childMeta2, _ := os.SetRecord(
   603  		ctx,
   604  		jetID,
   605  		core.GenesisPulse.PulseNumber,
   606  		&record.ChildRecord{
   607  			PrevChild: childMeta1,
   608  			Ref:       *child2Ref,
   609  		})
   610  	childMeta3, _ := os.SetRecord(
   611  		ctx,
   612  		jetID,
   613  		core.GenesisPulse.PulseNumber,
   614  		&record.ChildRecord{
   615  			PrevChild: childMeta2,
   616  			Ref:       *child3Ref,
   617  		})
   618  
   619  	parentIndex := index.ObjectLifeline{
   620  		LatestState:  parentID,
   621  		ChildPointer: childMeta3,
   622  	}
   623  	require.NoError(
   624  		s.T(),
   625  		os.SetObjectIndex(ctx, jetID, parentID, &parentIndex),
   626  	)
   627  
   628  	s.T().Run("returns correct children without pulse", func(t *testing.T) {
   629  		i, err := am.GetChildren(ctx, *genRefWithID(parentID), nil)
   630  		require.NoError(t, err)
   631  		child, err := i.Next()
   632  		assert.NoError(t, err)
   633  		assert.Equal(t, *child3Ref, *child)
   634  		child, err = i.Next()
   635  		assert.NoError(t, err)
   636  		assert.Equal(t, *child2Ref, *child)
   637  		child, err = i.Next()
   638  		assert.NoError(t, err)
   639  		assert.Equal(t, *child1Ref, *child)
   640  		hasNext := i.HasNext()
   641  		assert.False(t, hasNext)
   642  		_, err = i.Next()
   643  		assert.Error(t, err)
   644  	})
   645  
   646  	s.T().Run("returns correct children with pulse", func(t *testing.T) {
   647  		pn := core.PulseNumber(1)
   648  		i, err := am.GetChildren(ctx, *genRefWithID(parentID), &pn)
   649  		require.NoError(t, err)
   650  		child, err := i.Next()
   651  		assert.NoError(t, err)
   652  		assert.Equal(t, *child2Ref, *child)
   653  		child, err = i.Next()
   654  		assert.NoError(t, err)
   655  		assert.Equal(t, *child1Ref, *child)
   656  		hasNext := i.HasNext()
   657  		assert.NoError(t, err)
   658  		assert.False(t, hasNext)
   659  		_, err = i.Next()
   660  		assert.Error(t, err)
   661  	})
   662  
   663  	s.T().Run("returns correct children in many chunks", func(t *testing.T) {
   664  		am.getChildrenChunkSize = 1
   665  		i, err := am.GetChildren(ctx, *genRefWithID(parentID), nil)
   666  		require.NoError(t, err)
   667  		child, err := i.Next()
   668  		assert.NoError(t, err)
   669  		assert.Equal(t, *child3Ref, *child)
   670  		child, err = i.Next()
   671  		assert.NoError(t, err)
   672  		assert.Equal(t, *child2Ref, *child)
   673  		child, err = i.Next()
   674  		assert.NoError(t, err)
   675  		assert.Equal(t, *child1Ref, *child)
   676  		hasNext := i.HasNext()
   677  		assert.NoError(t, err)
   678  		assert.False(t, hasNext)
   679  		_, err = i.Next()
   680  		assert.Error(t, err)
   681  	})
   682  
   683  	s.T().Run("doesn't fail when has no children to return", func(t *testing.T) {
   684  		am.getChildrenChunkSize = 1
   685  		pn := core.PulseNumber(3)
   686  		i, err := am.GetChildren(ctx, *genRefWithID(parentID), &pn)
   687  		require.NoError(t, err)
   688  		child, err := i.Next()
   689  		assert.NoError(t, err)
   690  		assert.Equal(t, *child3Ref, *child)
   691  		child, err = i.Next()
   692  		assert.NoError(t, err)
   693  		assert.Equal(t, *child2Ref, *child)
   694  		child, err = i.Next()
   695  		assert.NoError(t, err)
   696  		assert.Equal(t, *child1Ref, *child)
   697  		hasNext := i.HasNext()
   698  		assert.NoError(t, err)
   699  		assert.False(t, hasNext)
   700  		_, err = i.Next()
   701  		assert.Error(t, err)
   702  	})
   703  }
   704  
   705  func makePulseStorage(s *amSuite) core.PulseStorage {
   706  	pulseStorage := storage.NewPulseStorage()
   707  	pulseStorage.PulseTracker = s.pulseTracker
   708  	pulse, err := s.pulseTracker.GetLatestPulse(s.ctx)
   709  	require.NoError(s.T(), err)
   710  	pulseStorage.Set(&pulse.Pulse)
   711  
   712  	return pulseStorage
   713  }
   714  
   715  func (s *amSuite) TestLedgerArtifactManager_GetChildren_FollowsRedirect() {
   716  	mc := minimock.NewController(s.T())
   717  	am := NewArtifactManger()
   718  	mb := testutils.NewMessageBusMock(mc)
   719  
   720  	am.DB = s.db
   721  	am.PulseStorage = makePulseStorage(s)
   722  
   723  	objRef := genRandomRef(0)
   724  	nodeRef := genRandomRef(0)
   725  	mb.SendFunc = func(c context.Context, m core.Message, o *core.MessageSendOptions) (r core.Reply, r1 error) {
   726  		o = o.Safe()
   727  		if o.Receiver == nil {
   728  			return &reply.GetChildrenRedirectReply{
   729  				Receiver: nodeRef,
   730  				Token:    &delegationtoken.GetChildrenRedirectToken{Signature: []byte{1, 2, 3}},
   731  			}, nil
   732  		}
   733  
   734  		token, ok := o.Token.(*delegationtoken.GetChildrenRedirectToken)
   735  		assert.True(s.T(), ok)
   736  		assert.Equal(s.T(), []byte{1, 2, 3}, token.Signature)
   737  		assert.Equal(s.T(), nodeRef, o.Receiver)
   738  		return &reply.Children{}, nil
   739  	}
   740  	am.DefaultBus = mb
   741  
   742  	_, err := am.GetChildren(s.ctx, *objRef, nil)
   743  	require.NoError(s.T(), err)
   744  }
   745  
   746  func (s *amSuite) TestLedgerArtifactManager_HandleJetDrop() {
   747  	s.T().Skip("jet drops are for validation and it doesn't work")
   748  
   749  	ctx, os, am := getTestData(s)
   750  
   751  	codeRecord := record.CodeRecord{
   752  		Code: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{1, 2, 3, 3, 2, 1}),
   753  	}
   754  
   755  	setRecordMessage := message.SetRecord{
   756  		Record: record.SerializeRecord(&codeRecord),
   757  	}
   758  
   759  	jetID := *jet.NewID(0, nil)
   760  
   761  	rep, err := am.DefaultBus.Send(ctx, &message.JetDrop{
   762  		JetID: jetID,
   763  		Messages: [][]byte{
   764  			message.ToBytes(&setRecordMessage),
   765  		},
   766  		PulseNumber: core.GenesisPulse.PulseNumber,
   767  	}, nil)
   768  	assert.NoError(s.T(), err)
   769  	assert.Equal(s.T(), reply.OK{}, *rep.(*reply.OK))
   770  
   771  	id := record.NewRecordIDFromRecord(s.scheme, 0, &codeRecord)
   772  	rec, err := os.GetRecord(ctx, jetID, id)
   773  	require.NoError(s.T(), err)
   774  	assert.Equal(s.T(), codeRecord, *rec.(*record.CodeRecord))
   775  }
   776  
   777  func (s *amSuite) TestLedgerArtifactManager_RegisterValidation() {
   778  	mc := minimock.NewController(s.T())
   779  	defer mc.Finish()
   780  
   781  	mb := testmessagebus.NewTestMessageBus(s.T())
   782  	mb.PulseStorage = makePulseStorage(s)
   783  	jc := testutils.NewJetCoordinatorMock(mc)
   784  	jc.IsBeyondLimitMock.Return(false, nil)
   785  	jc.NodeForJetMock.Return(&core.RecordRef{}, nil)
   786  
   787  	indexMock := recentstorage.NewRecentIndexStorageMock(s.T())
   788  	pendingMock := recentstorage.NewPendingStorageMock(s.T())
   789  
   790  	indexMock.AddObjectMock.Return()
   791  	pendingMock.GetRequestsForObjectMock.Return(nil)
   792  	pendingMock.AddPendingRequestMock.Return()
   793  	pendingMock.RemovePendingRequestMock.Return()
   794  
   795  	provideMock := recentstorage.NewProviderMock(s.T())
   796  	provideMock.GetIndexStorageMock.Return(indexMock)
   797  	provideMock.GetPendingStorageMock.Return(pendingMock)
   798  	provideMock.CountMock.Return(0)
   799  
   800  	certificate := testutils.NewCertificateMock(s.T())
   801  	certificate.GetRoleMock.Return(core.StaticRoleLightMaterial)
   802  
   803  	handler := MessageHandler{
   804  		replayHandlers:             map[core.MessageType]core.MessageHandler{},
   805  		PlatformCryptographyScheme: s.scheme,
   806  		conf:        &configuration.Ledger{LightChainLimit: 3, PendingRequestsLimit: 10},
   807  		certificate: certificate,
   808  	}
   809  
   810  	handler.Bus = mb
   811  	handler.JetCoordinator = jc
   812  	handler.DBContext = s.db
   813  	handler.ObjectStorage = s.objectStorage
   814  	handler.PulseTracker = s.pulseTracker
   815  	handler.Nodes = s.nodeStorage
   816  	handler.JetStorage = s.jetStorage
   817  
   818  	handler.RecentStorageProvider = provideMock
   819  
   820  	err := handler.Init(s.ctx)
   821  	require.NoError(s.T(), err)
   822  
   823  	amPulseStorageMock := testutils.NewPulseStorageMock(s.T())
   824  	amPulseStorageMock.CurrentFunc = func(p context.Context) (r *core.Pulse, r1 error) {
   825  		pulse, err := s.pulseTracker.GetLatestPulse(p)
   826  		require.NoError(s.T(), err)
   827  		return &pulse.Pulse, err
   828  	}
   829  
   830  	am := LedgerArtifactManager{
   831  		DB:                         s.db,
   832  		DefaultBus:                 mb,
   833  		getChildrenChunkSize:       100,
   834  		PlatformCryptographyScheme: s.scheme,
   835  		PulseStorage:               amPulseStorageMock,
   836  		GenesisState:               s.genesisState,
   837  	}
   838  
   839  	objID, err := am.RegisterRequest(
   840  		s.ctx,
   841  		*am.GenesisRef(),
   842  		&message.Parcel{
   843  			Msg: &message.GenesisRequest{
   844  				Name: "4K3NiGuqYGqKPnYp6XeGd2kdN4P9veL6rYcWkLKWXZCu.4FFB8zfQoGznSmzDxwv4njX1aR9ioL8GHSH17QXH2AFa",
   845  			},
   846  		},
   847  	)
   848  	require.NoError(s.T(), err)
   849  	objRef := genRefWithID(objID)
   850  
   851  	desc, err := am.ActivateObject(
   852  		s.ctx,
   853  		domainRef,
   854  		*objRef,
   855  		*am.GenesisRef(),
   856  		*genRandomRef(0),
   857  		false,
   858  		[]byte{1},
   859  	)
   860  	require.NoError(s.T(), err)
   861  	stateID1 := desc.StateID()
   862  
   863  	desc, err = am.GetObject(s.ctx, *objRef, nil, false)
   864  	require.NoError(s.T(), err)
   865  	require.Equal(s.T(), *stateID1, *desc.StateID())
   866  
   867  	_, err = am.GetObject(s.ctx, *objRef, nil, true)
   868  	require.Equal(s.T(), err, core.ErrStateNotAvailable)
   869  
   870  	desc, err = am.GetObject(s.ctx, *objRef, nil, false)
   871  	require.NoError(s.T(), err)
   872  	desc, err = am.UpdateObject(
   873  		s.ctx,
   874  		domainRef,
   875  		*genRandomRef(0),
   876  		desc,
   877  		[]byte{3},
   878  	)
   879  	require.NoError(s.T(), err)
   880  	stateID3 := desc.StateID()
   881  	err = am.RegisterValidation(s.ctx, *objRef, *stateID1, true, nil)
   882  	require.NoError(s.T(), err)
   883  
   884  	desc, err = am.GetObject(s.ctx, *objRef, nil, false)
   885  	assert.NoError(s.T(), err)
   886  	assert.Equal(s.T(), *stateID3, *desc.StateID())
   887  	desc, err = am.GetObject(s.ctx, *objRef, nil, true)
   888  	assert.NoError(s.T(), err)
   889  	assert.Equal(s.T(), *stateID1, *desc.StateID())
   890  }
   891  
   892  func (s *amSuite) TestLedgerArtifactManager_RegisterResult() {
   893  	ctx, os, am := getTestData(s)
   894  
   895  	objID := core.RecordID{1, 2, 3}
   896  	request := genRandomRef(0)
   897  	requestID, err := am.RegisterResult(ctx, *core.NewRecordRef(core.RecordID{}, objID), *request, []byte{1, 2, 3})
   898  	assert.NoError(s.T(), err)
   899  
   900  	rec, err := os.GetRecord(ctx, *jet.NewID(0, nil), requestID)
   901  	assert.NoError(s.T(), err)
   902  	assert.Equal(s.T(), record.ResultRecord{
   903  		Object:  objID,
   904  		Request: *request,
   905  		Payload: []byte{1, 2, 3},
   906  	}, *rec.(*record.ResultRecord))
   907  }
   908  
   909  func (s *amSuite) TestLedgerArtifactManager_RegisterRequest_JetMiss() {
   910  	mc := minimock.NewController(s.T())
   911  	defer mc.Finish()
   912  
   913  	cs := platformpolicy.NewPlatformCryptographyScheme()
   914  	am := NewArtifactManger()
   915  	am.PlatformCryptographyScheme = cs
   916  	pulseStorageMock := testutils.NewPulseStorageMock(s.T())
   917  	pulseStorageMock.CurrentFunc = func(ctx context.Context) (*core.Pulse, error) {
   918  		return &core.Pulse{PulseNumber: core.FirstPulseNumber}, nil
   919  	}
   920  
   921  	am.PulseStorage = pulseStorageMock
   922  	am.GenesisState = s.genesisState
   923  	am.JetStorage = s.jetStorage
   924  
   925  	s.T().Run("returns error on exceeding retry limit", func(t *testing.T) {
   926  		mb := testutils.NewMessageBusMock(mc)
   927  		am.DefaultBus = mb
   928  		mb.SendMock.Return(&reply.JetMiss{JetID: *jet.NewID(5, []byte{1, 2, 3}), Pulse: core.FirstPulseNumber}, nil)
   929  		_, err := am.RegisterRequest(s.ctx, *am.GenesisRef(), &message.Parcel{Msg: &message.CallMethod{}})
   930  		require.Error(t, err)
   931  	})
   932  
   933  	s.T().Run("returns no error and updates tree when jet miss", func(t *testing.T) {
   934  		mb := testutils.NewMessageBusMock(mc)
   935  		am.DefaultBus = mb
   936  		retries := 3
   937  		mb.SendFunc = func(c context.Context, m core.Message, o *core.MessageSendOptions) (r core.Reply, r1 error) {
   938  			if retries == 0 {
   939  				return &reply.ID{}, nil
   940  			}
   941  			retries--
   942  			return &reply.JetMiss{JetID: *jet.NewID(4, []byte{0xD5}), Pulse: core.FirstPulseNumber}, nil
   943  		}
   944  		_, err := am.RegisterRequest(s.ctx, *am.GenesisRef(), &message.Parcel{Msg: &message.CallMethod{}})
   945  		require.NoError(t, err)
   946  
   947  		jetID, actual := s.jetStorage.FindJet(
   948  			s.ctx, core.FirstPulseNumber, *core.NewRecordID(0, []byte{0xD5}),
   949  		)
   950  		assert.Equal(t, *jet.NewID(4, []byte{0xD0}), *jetID)
   951  		assert.True(t, actual)
   952  	})
   953  }
   954  
   955  func (s *amSuite) TestLedgerArtifactManager_GetRequest_Success() {
   956  	// Arrange
   957  	mc := minimock.NewController(s.T())
   958  	defer mc.Finish()
   959  	objectID := testutils.RandomID()
   960  	requestID := testutils.RandomID()
   961  
   962  	node := testutils.RandomRef()
   963  
   964  	jc := testutils.NewJetCoordinatorMock(mc)
   965  	jc.NodeForObjectMock.Return(&node, nil)
   966  
   967  	pulseStorageMock := testutils.NewPulseStorageMock(mc)
   968  	pulseStorageMock.CurrentMock.Return(core.GenesisPulse, nil)
   969  
   970  	var parcel core.Parcel = &message.Parcel{PulseNumber: 123987}
   971  	resRecord := record.RequestRecord{
   972  		Parcel: message.ParcelToBytes(parcel),
   973  	}
   974  	finalResponse := &reply.Request{Record: record.SerializeRecord(&resRecord)}
   975  
   976  	mb := testutils.NewMessageBusMock(s.T())
   977  	mb.SendFunc = func(p context.Context, p1 core.Message, p2 *core.MessageSendOptions) (r core.Reply, r1 error) {
   978  		switch mb.SendCounter {
   979  		case 0:
   980  			casted, ok := p1.(*message.GetPendingRequestID)
   981  			require.Equal(s.T(), true, ok)
   982  			require.Equal(s.T(), objectID, casted.ObjectID)
   983  			return &reply.ID{ID: requestID}, nil
   984  		case 1:
   985  			casted, ok := p1.(*message.GetRequest)
   986  			require.Equal(s.T(), true, ok)
   987  			require.Equal(s.T(), requestID, casted.Request)
   988  			require.Equal(s.T(), node, *p2.Receiver)
   989  			return finalResponse, nil
   990  		default:
   991  			panic("test is totally broken")
   992  		}
   993  	}
   994  
   995  	am := NewArtifactManger()
   996  	am.JetCoordinator = jc
   997  	am.DefaultBus = mb
   998  	am.PulseStorage = pulseStorageMock
   999  
  1000  	// Act
  1001  	res, err := am.GetPendingRequest(inslogger.TestContext(s.T()), objectID)
  1002  
  1003  	// Assert
  1004  	require.NoError(s.T(), err)
  1005  	require.Equal(s.T(), parcel, res)
  1006  
  1007  }