public async Task TestEmptyContract()
        {
            var chainId                = Hash.Generate();
            var runner                 = _smartContractRunnerFactory.GetRunner(0);
            var contractCType          = typeof(TestContractC);
            var contractBType          = typeof(TestContractB);
            var contractAType          = typeof(TestContractA);
            var nonAttrContract1Type   = typeof(TestNonAttrContract1);
            var nonAttrContract2Type   = typeof(TestNonAttrContract2);
            var refNonAttrContractType = typeof(TestRefNonAttrContract);

            var contractCTemplate          = runner.ExtractMetadata(contractCType);
            var contractBTemplate          = runner.ExtractMetadata(contractBType);
            var contractATemplate          = runner.ExtractMetadata(contractAType);
            var nonAttrContract1Template   = runner.ExtractMetadata(nonAttrContract1Type);
            var nonAttrContract2Template   = runner.ExtractMetadata(nonAttrContract2Type);
            var refNonAttrContractTemplate = runner.ExtractMetadata(refNonAttrContractType);


            var contract1Addr   = Address.FromString("TestNonAttrContract1");   // 0x3f77405cbfe1e48e2fa0e4bf6a4e5917f768
            var contract2Addr   = Address.FromString("TestNonAttrContract2");   // 0xb4e0cc36ede5d518fbabd1ed5498093e4b71
            var refContractAddr = Address.FromString("TestRefNonAttrContract"); // 0x7c7f78ecc9f78be2a502e5bf9f22112c6a47

            var addrA = Address.FromString("TestContractA");                    // 0x46c86551bca0e3120ca0f831f53d8cb55ac7
            var addrB = Address.FromString("TestContractB");                    // 0xea0e38633e550dc4b7914010c2d7c95086ee
            var addrC = Address.FromString("TestContractC");                    // 0x053f751c35f7c681be14bcee03085dc8a309

            await _functionMetadataService.DeployContract(chainId, addrC, contractCTemplate);

            await _functionMetadataService.DeployContract(chainId, addrB, contractBTemplate);

            await _functionMetadataService.DeployContract(chainId, addrA, contractATemplate);

            await _functionMetadataService.DeployContract(chainId, contract1Addr, nonAttrContract1Template);

            await _functionMetadataService.DeployContract(chainId, contract2Addr, nonAttrContract2Template);

            await _functionMetadataService.DeployContract(chainId, refContractAddr, refNonAttrContractTemplate);

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource4", DataAccessMode.AccountSpecific)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrC.DumpHex() + ".Func0"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource5", DataAccessMode.ReadOnlyAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrC.DumpHex() + ".Func1"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrC.DumpHex() + ".Func1"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource5", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.AccountSpecific),
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrB.DumpHex() + ".Func0"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource3", DataAccessMode.ReadOnlyAccountSharing),
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrB.DumpHex() + ".Func1"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>()), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func0(int)"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func1"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource0", DataAccessMode.AccountSpecific),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func0"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func2"
            }),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func1"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func2"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func0",
                addrB.DumpHex() + ".Func0",
                addrC.DumpHex() + ".Func0"
            }),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource0", DataAccessMode.AccountSpecific),
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.AccountSpecific),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource5", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource4", DataAccessMode.AccountSpecific),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func3"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func2"
            }),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func4"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func3",
                addrB.DumpHex() + ".Func1"
            }),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource0", DataAccessMode.AccountSpecific),
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource3", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.AccountSpecific),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource5", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource4", DataAccessMode.AccountSpecific),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func5"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, contract1Addr.DumpHex() + ".Func1"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, contract1Addr.DumpHex() + ".Func2"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(contract2Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, contract2Addr.DumpHex() + ".Func1"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(contract2Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, contract2Addr.DumpHex() + ".Func2"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new [] { contract1Addr.DumpHex() + ".Func1" }),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, refContractAddr.DumpHex() + ".Func1"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new [] { contract1Addr.DumpHex() + ".Func1" }),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing),
                new Resource(refContractAddr.Value.ToByteArray().ToHex() + ".localRes", DataAccessMode.AccountSpecific)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, refContractAddr.DumpHex() + ".Func1_1"))));
            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new [] { contract1Addr.DumpHex() + ".Func2" }),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing),
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, refContractAddr.DumpHex() + ".Func2"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                contract1Addr.DumpHex() + ".Func2",
                refContractAddr.DumpHex() + ".Func1_1"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing),
                new Resource(refContractAddr.Value.ToByteArray().ToHex() + ".localRes", DataAccessMode.AccountSpecific)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, refContractAddr.DumpHex() + ".Func2_1"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                contract1Addr.DumpHex() + ".Func2",
                refContractAddr.DumpHex() + ".Func1"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing),
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, refContractAddr.DumpHex() + ".Func2_2"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                contract1Addr.DumpHex() + ".Func1",
                contract1Addr.DumpHex() + ".Func2"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing),
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, refContractAddr.DumpHex() + ".Func3"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                contract1Addr.DumpHex() + ".Func1",
                contract2Addr.DumpHex() + ".Func1"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing),
                new Resource(contract2Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, refContractAddr.DumpHex() + ".Func4"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                contract1Addr.DumpHex() + ".Func2",
                addrC.DumpHex() + ".Func0"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(contract1Addr.Value.ToByteArray().ToHex() + "._lock", DataAccessMode.ReadWriteAccountSharing),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource4", DataAccessMode.AccountSpecific),
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, refContractAddr.DumpHex() + ".Func5"))));

            var callGraph = new SerializedCallGraph
            {
                Vertices =
                {
                    addrC.DumpHex() + ".Func0",
                    addrC.DumpHex() + ".Func1",
                    addrB.DumpHex() + ".Func0",
                    addrB.DumpHex() + ".Func1",
                    addrA.DumpHex() + ".Func0(int)",
                    addrA.DumpHex() + ".Func0",
                    addrA.DumpHex() + ".Func1",
                    addrA.DumpHex() + ".Func2",
                    addrA.DumpHex() + ".Func3",
                    addrA.DumpHex() + ".Func4",
                    addrA.DumpHex() + ".Func5",

                    contract1Addr.DumpHex() + ".Func1",
                    contract1Addr.DumpHex() + ".Func2",
                    contract2Addr.DumpHex() + ".Func1",
                    contract2Addr.DumpHex() + ".Func2",
                    refContractAddr.DumpHex() + ".Func1",
                    refContractAddr.DumpHex() + ".Func1_1",
                    refContractAddr.DumpHex() + ".Func2",
                    refContractAddr.DumpHex() + ".Func2_1",
                    refContractAddr.DumpHex() + ".Func2_2",
                    refContractAddr.DumpHex() + ".Func3",
                    refContractAddr.DumpHex() + ".Func4",
                    refContractAddr.DumpHex() + ".Func5"
                },
                Edges =
                {
                    new GraphEdge
                    {
                        Source = addrB.DumpHex() + ".Func0",
                        Target = addrC.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func0",
                        Target = addrA.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func1",
                        Target = addrA.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func3",
                        Target = addrB.DumpHex() + ".Func0"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func3",
                        Target = addrA.DumpHex() + ".Func0"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func3",
                        Target = addrC.DumpHex() + ".Func0"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func4",
                        Target = addrA.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func5",
                        Target = addrB.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func5",
                        Target = addrA.DumpHex() + ".Func3"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func1",
                        Target = contract1Addr.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func1_1",
                        Target = contract1Addr.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func2",
                        Target = contract1Addr.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func2_1",
                        Target = contract1Addr.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func2_1",
                        Target = refContractAddr.DumpHex() + ".Func1_1"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func2_2",
                        Target = contract1Addr.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func2_2",
                        Target = refContractAddr.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func3",
                        Target = contract1Addr.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func3",
                        Target = contract1Addr.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func4",
                        Target = contract1Addr.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func4",
                        Target = contract2Addr.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func5",
                        Target = contract1Addr.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = refContractAddr.DumpHex() + ".Func5",
                        Target = addrC.DumpHex() + ".Func0"
                    }
                }
            };

            Assert.Equal(callGraph, await _dataStore.GetAsync <SerializedCallGraph>(chainId.OfType(HashType.CallingGraph)));
        }
        public async Task TestDepolyContract()
        {
            var chainId       = Hash.Generate();
            var runner        = _smartContractRunnerFactory.GetRunner(0);
            var contractCType = typeof(TestContractC);
            var contractBType = typeof(TestContractB);
            var contractAType = typeof(TestContractA);

            var contractCTemplate = runner.ExtractMetadata(contractCType);
            var contractBTemplate = runner.ExtractMetadata(contractBType);
            var contractATemplate = runner.ExtractMetadata(contractAType);

            var addrA = Address.FromString("TestContractA");
            var addrB = Address.FromString("TestContractB");
            var addrC = Address.FromString("TestContractC");

            Console.WriteLine(addrC);

            await _functionMetadataService.DeployContract(chainId, addrC, contractCTemplate);

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource4", DataAccessMode.AccountSpecific)
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrC.DumpHex() + ".Func0")));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource5", DataAccessMode.ReadOnlyAccountSharing)
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrC.DumpHex() + ".Func1")));

            await _functionMetadataService.DeployContract(chainId, addrB, contractBTemplate);

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrC.DumpHex() + ".Func1"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource5", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.AccountSpecific),
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrB.DumpHex() + ".Func0")));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new []
            {
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource3", DataAccessMode.ReadOnlyAccountSharing),
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrB.DumpHex() + ".Func1")));

            await _functionMetadataService.DeployContract(chainId, addrA, contractATemplate);

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>()), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func0(int)")));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func1"
            }),
                             new HashSet <Resource>(new []
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource0", DataAccessMode.AccountSpecific),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func0")));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func2"
            }),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func1")));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), (await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func2"))));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func0",
                addrB.DumpHex() + ".Func0",
                addrC.DumpHex() + ".Func0"
            }),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource0", DataAccessMode.AccountSpecific),
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.AccountSpecific),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource5", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource4", DataAccessMode.AccountSpecific),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func3")));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func2"
            }),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func4")));

            Assert.Equal(new FunctionMetadata(
                             new HashSet <string>(new []
            {
                addrA.DumpHex() + ".Func3",
                addrB.DumpHex() + ".Func1"
            }),
                             new HashSet <Resource>(new[]
            {
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource0", DataAccessMode.AccountSpecific),
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource3", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrB.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.AccountSpecific),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource5", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrC.Value.ToByteArray().ToHex() + ".resource4", DataAccessMode.AccountSpecific),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource1", DataAccessMode.ReadOnlyAccountSharing),
                new Resource(addrA.Value.ToByteArray().ToHex() + ".resource2", DataAccessMode.ReadWriteAccountSharing)
            })), await _dataStore.GetAsync <FunctionMetadata>(DataPath.CalculatePointerForMetadata(chainId, addrA.DumpHex() + ".Func5")));

            var callGraph = new SerializedCallGraph
            {
                Vertices =
                {
                    addrC.DumpHex() + ".Func0",
                    addrC.DumpHex() + ".Func1",
                    addrB.DumpHex() + ".Func0",
                    addrB.DumpHex() + ".Func1",
                    addrA.DumpHex() + ".Func0(int)",
                    addrA.DumpHex() + ".Func0",
                    addrA.DumpHex() + ".Func1",
                    addrA.DumpHex() + ".Func2",
                    addrA.DumpHex() + ".Func3",
                    addrA.DumpHex() + ".Func4",
                    addrA.DumpHex() + ".Func5"
                },
                Edges =
                {
                    new GraphEdge
                    {
                        Source = addrB.DumpHex() + ".Func0",
                        Target = addrC.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func0",
                        Target = addrA.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func1",
                        Target = addrA.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func3",
                        Target = addrB.DumpHex() + ".Func0"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func3",
                        Target = addrA.DumpHex() + ".Func0"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func3",
                        Target = addrC.DumpHex() + ".Func0"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func4",
                        Target = addrA.DumpHex() + ".Func2"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func5",
                        Target = addrB.DumpHex() + ".Func1"
                    },
                    new GraphEdge
                    {
                        Source = addrA.DumpHex() + ".Func5",
                        Target = addrA.DumpHex() + ".Func3"
                    }
                }
            };

            Assert.Equal(callGraph, await _dataStore.GetAsync <SerializedCallGraph>(chainId.OfType(HashType.CallingGraph)));
        }
 public async Task AddCallGraphAsync(SerializedCallGraph callGraph)
 {
     await _callGraphStore.SetAsync(_chainId.ToStorageKey(), callGraph);
 }