public override Empty Play(SInt64Value input)
        {
            Assert(input.Value > 1, "Invalid money.");
            var playerInformation = State.PlayerInformation[Context.Sender];

            Assert(playerInformation != null, "Not registered.");
            if (playerInformation == null)
            {
                return(new Empty());
            }

            Context.LogDebug(() => $"Playing with amount {input.Value}");

            State.TokenContract.TransferFrom.Send(new TransferFromInput
            {
                From   = Context.Sender,
                To     = Context.Self,
                Amount = input.Value,
                Symbol = BingoGameContractConstants.CardSymbol,
                Memo   = "Play the game."
            });

            playerInformation.BingoInfos.Add(new BingoInformation
            {
                PlayRoundNumber = State.ConsensusContract.GetCurrentRoundNumber.Call(new Empty()).Value,
                Amount          = input.Value,
                PlayId          = Context.TransactionId
            });

            State.PlayerInformation[Context.Sender] = playerInformation;
            return(new Empty());
        }
Пример #2
0
        public override Empty SetTransactionSizeUnitPrice(SInt64Value input)
        {
            if (State.ZeroContract.Value == null)
            {
                State.ZeroContract.Value = Context.GetZeroSmartContractAddress();
            }

            if (State.ParliamentAuthContract.Value == null)
            {
                State.ParliamentAuthContract.Value =
                    Context.GetContractAddressByName(SmartContractConstants.ParliamentAuthContractSystemName);
            }

            var contractOwner = State.ZeroContract.GetContractAuthor.Call(Context.Self);

            Assert(
                contractOwner == Context.Sender ||
                Context.Sender == State.ParliamentAuthContract.GetGenesisOwnerAddress.Call(new Empty()) ||
                Context.Sender == Context.GetContractAddressByName(SmartContractConstants.EconomicContractSystemName),
                "No permission to set tx size unit price.");

            Context.Fire(new TransactionSizeFeeUnitPriceUpdated
            {
                UnitPrice = input.Value
            });

            Context.LogDebug(() => $"SetTransactionSizeUnitPrice: {input.Value}");

            State.TransactionFeeUnitPrice.Value = input.Value;

            return(new Empty());
        }
        public override Empty Deposit(SInt64Value input)
        {
            var playerInformation = State.PlayerInformation[Context.Sender];

            Assert(playerInformation != null, $"User {Context.Sender} not registered before.");
            Assert(input.Value > 0, "At least you should buy 1 CARD.");
            var elfAmount = input.Value.Mul(1_0000_0000);

            State.TokenContract.TransferFrom.Send(new TransferFromInput
            {
                Symbol = Context.Variables.NativeSymbol,
                Amount = elfAmount,
                From   = Context.Sender,
                To     = Context.Self,
                Memo   = "Thanks for recharging:)"
            });
            State.TokenContract.Transfer.Send(new TransferInput
            {
                Symbol = BingoGameContractConstants.CardSymbol,
                Amount = input.Value,
                To     = Context.Sender,
                Memo   = "Now you are stronger:)"
            });

            return(new Empty());
        }
Пример #4
0
        public override CrossChainBlockData GetIndexedCrossChainBlockDataByHeight(SInt64Value input)
        {
            var indexedCrossChainBlockData = State.IndexedCrossChainBlockData[input.Value];

            Assert(indexedCrossChainBlockData != null);
            return(indexedCrossChainBlockData);
        }
Пример #5
0
        public async Task QueryMinedBlockCountInCurrentTerm()
        {
            await PrepareConsensusWithCandidateEnvironment();

            SInt64Value count = new SInt64Value
            {
                Value = 0
            };

            foreach (var bpInfo in MinersKeyPairs)
            {
                var input = new PublicKey
                {
                    Hex = bpInfo.PublicKey.ToHex()
                };
                var bytes = await Starter.CallContractMethodAsync(Starter.GetConsensusContractAddress(),
                                                                  nameof(ConsensusContract.QueryMinedBlockCountInCurrentTerm), input);

                count = SInt64Value.Parser.ParseFrom(bytes);

                if (count.Value > 0)
                {
                    break;
                }
            }

            count.Value.ShouldBeGreaterThanOrEqualTo(1L);
        }
Пример #6
0
        public async Task Get_RoundInformation()
        {
            //query return null
            {
                var input = new SInt64Value
                {
                    Value = 2
                };
                var roundInformation = await Starter.CallContractMethodAsync(Starter.GetConsensusContractAddress(),
                                                                             nameof(ConsensusContract.GetRoundInformation), input);

                var round = Round.Parser.ParseFrom(roundInformation);
                round.ShouldBe(new Round());
            }

            //query with result
            {
                var input = new SInt64Value
                {
                    Value = 1
                };
                var roundInformation = await Starter.CallContractMethodAsync(Starter.GetConsensusContractAddress(),
                                                                             nameof(ConsensusContract.GetRoundInformation), input);

                var round = Round.Parser.ParseFrom(roundInformation);
                round.ShouldNotBeNull();
                round.RoundNumber.ShouldBe(1);
                round.RealTimeMinersInformation.Count.ShouldBe(3);
            }
        }
        public override SInt64Value Play(SInt64Value input)
        {
            Assert(input.Value > 1, "Invalid bet amount.");
            var playerInformation = State.PlayerInformation[Context.Sender];

            Assert(playerInformation != null, $"User {Context.Sender} not registered before.");

            Context.LogDebug(() => $"Playing with amount {input.Value}");

            State.TokenContract.TransferFrom.Send(new TransferFromInput
            {
                From   = Context.Sender,
                To     = Context.Self,
                Amount = input.Value,
                Symbol = BingoGameContractConstants.CardSymbol,
                Memo   = "Enjoy!"
            });

            var currentRound = State.ConsensusContract.GetCurrentRoundInformation.Call(new Empty());

            playerInformation.Bouts.Add(new BoutInformation
            {
                // Record current round number.
                PlayRoundNumber = currentRound.RoundNumber,
                Amount          = input.Value,
                PlayId          = Context.TransactionId
            });

            State.PlayerInformation[Context.Sender] = playerInformation;

            return(new SInt64Value {
                Value = CalculateWaitingMilliseconds(currentRound)
            });
        }
Пример #8
0
        public async Task GetTermNumberByRoundNumber()
        {
            await PrepareConsensusWithCandidateEnvironment();

            var input = new SInt64Value()
            {
                Value = 1
            };
            var bytes = await Starter.CallContractMethodAsync(Starter.GetConsensusContractAddress(),
                                                              nameof(ConsensusContract.GetTermNumberByRoundNumber), input);

            var termNumber = SInt64Value.Parser.ParseFrom(bytes).Value;

            termNumber.ShouldBe(0L);

            var roundBytes = await Starter.CallContractMethodAsync(Starter.GetConsensusContractAddress(),
                                                                   nameof(ConsensusContract.GetCurrentRoundNumber), new Empty());

            var currentRoundNumber = SInt64Value.Parser.ParseFrom(roundBytes).Value;

            var termBytes = await Starter.CallContractMethodAsync(Starter.GetConsensusContractAddress(),
                                                                  nameof(ConsensusContract.GetCurrentTermNumber), new Empty());

            var currentTermNumber = SInt64Value.Parser.ParseFrom(termBytes).Value;

            input.Value = currentRoundNumber;
            bytes       = await Starter.CallContractMethodAsync(Starter.GetConsensusContractAddress(),
                                                                nameof(ConsensusContract.GetTermNumberByRoundNumber), input);

            termNumber = SInt64Value.Parser.ParseFrom(bytes).Value;
            termNumber.ShouldBe(currentTermNumber);
        }
Пример #9
0
        public override SInt64Value GetTermNumberByRoundNumber(SInt64Value input)
        {
            var map = State.TermNumberLookupField.Value.Map;

            Assert(map != null, "Term number not found.");
            var roundNumber = map?.OrderBy(p => p.Key).Last(p => input.Value >= p.Value).Key ?? (long)0;

            return(new SInt64Value {
                Value = roundNumber
            });
        }
Пример #10
0
        /// <summary>
        /// Initial miners can set blockchain age manually.
        /// For testing.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override Empty SetBlockchainAge(SInt64Value input)
        {
            Assert(TryToGetRoundInformation(1, out var firstRound),
                   ContractErrorCode.GetErrorMessage(ContractErrorCode.NotFound, "Failed to get first round information"));
            Assert(firstRound.RealTimeMinersInformation.Keys.Contains(Context.RecoverPublicKey().ToHex()),
                   ContractErrorCode.GetErrorMessage(ContractErrorCode.NoPermission,
                                                     "No permission to change blockchain age."));
            // Don't use `UpdateBlockchainAge` here. Because in testing, we can set blockchain age for free.
            State.AgeField.Value = input.Value;

            LogVerbose($"{Context.RecoverPublicKey().ToHex()} set blockchain age to {input.Value}");

            return(new Empty());
        }
Пример #11
0
        public override CrossChainBlockData GetIndexedCrossChainBlockDataByHeight(SInt64Value input)
        {
            var crossChainBlockData         = new CrossChainBlockData();
            var indexedParentChainBlockData = State.LastIndexedParentChainBlockData.Value;

            if (indexedParentChainBlockData != null && indexedParentChainBlockData.LocalChainHeight == input.Value)
            {
                crossChainBlockData.ParentChainBlockData.AddRange(indexedParentChainBlockData.ParentChainBlockData);
            }

            var indexedSideChainBlockData = GetIndexedSideChainBlockDataByHeight(input);

            crossChainBlockData.SideChainBlockData.AddRange(indexedSideChainBlockData.SideChainBlockData);
            return(crossChainBlockData);
        }
Пример #12
0
        /// <summary>
        /// Converts the serialized protobuf data to human friendly representation.
        /// </summary>
        /// <returns></returns>
        public byte[] ToFriendlyBytes()
        {
            switch (Type)
            {
            case Types.RetType.Bool:
                var boolval = new BoolValue();
                ((IMessage)boolval).MergeFrom(this.Data);
                return(BitConverter.GetBytes(boolval.Value));

            case Types.RetType.Int32:
                var sint32Val = new SInt32Value();
                ((IMessage)sint32Val).MergeFrom(this.Data);
                return(GetFriendlyBytes(sint32Val.Value));

            case Types.RetType.Uint32:
                var uint32Val = new UInt32Value();
                ((IMessage)uint32Val).MergeFrom(this.Data);
                return(GetFriendlyBytes(uint32Val.Value));

            case Types.RetType.Int64:
                var sint64Val = new SInt64Value();
                ((IMessage)sint64Val).MergeFrom(this.Data);
                return(GetFriendlyBytes(sint64Val.Value));

            case Types.RetType.Uint64:
                var uint64Val = new UInt64Value();
                ((IMessage)uint64Val).MergeFrom(this.Data);
                return(GetFriendlyBytes(uint64Val.Value));

            case Types.RetType.String:
                var stringVal = new StringValue();
                ((IMessage)stringVal).MergeFrom(this.Data);
                return(GetFriendlyBytes(stringVal.Value));

            case Types.RetType.Bytes:
                var bytesVal = new BytesValue();
                ((IMessage)bytesVal).MergeFrom(this.Data);
                return(GetFriendlyBytes(bytesVal.Value.ToByteArray()));

            case Types.RetType.PbMessage:
            case Types.RetType.UserType:
                // Both are treated as bytes
                return(GetFriendlyBytes(Data.ToByteArray()));
            }

            return(new byte[0]);
        }
Пример #13
0
        public async Task GetTermSnapshot()
        {
            await PrepareConsensusWithCandidateEnvironment();

            var input = new SInt64Value
            {
                Value = 1
            };
            var bytes = await Starter.CallContractMethodAsync(Starter.GetConsensusContractAddress(),
                                                              nameof(ConsensusContract.GetTermSnapshot), input);

            var termSnapshot = TermSnapshot.Parser.ParseFrom(bytes);

            termSnapshot.TermNumber.ShouldBe(input.Value);
            termSnapshot.EndRoundNumber.ShouldBe(input.Value + 1);
            termSnapshot.CandidatesSnapshot.Count.ShouldBe(MinersCount);
        }
Пример #14
0
        public override Empty SendTransferFromAsInlineTx(SInt64Value input)
        {
            if (State.TokenContract.Value == null)
            {
                State.TokenContract.Value =
                    Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName);
            }

            State.TokenContract.TransferFrom.Send(new TransferFromInput
            {
                From   = Context.Sender,
                To     = Context.Self,
                Amount = input.Value,
                Symbol = "ELF"
            });

            return(new Empty());
        }
Пример #15
0
        public override ActionResult KeepWeights(SInt64Value input)
        {
            var oldTermNumber = input.Value;
            var totalWeights  = State.TotalWeightsMap[oldTermNumber];

            if (totalWeights > 0)
            {
                Context.LogDebug(() => "[Forwarding weights]");
                AddWeights(new WeightsInfo()
                {
                    TermNumber = oldTermNumber + 1,
                    Weights    = totalWeights
                });
            }

            return(new ActionResult {
                Success = true
            });
        }
Пример #16
0
        /// <summary>
        /// Withdraw specific amount owed to the foundation. Only foundation can perform this action.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override Empty Withdraw(SInt64Value input)
        {
            var amount = input.Value;

            Assert(Context.Sender == State.FoundationAddress.Value, "Only foundation can withdraw token.");
            var owed = State.OwedToFoundation.Value;

            Assert(owed >= amount, "Too much to withdraw.");
            if (amount > 0)
            {
                State.TokenContract.Transfer.Send(new TransferInput
                {
                    To     = State.FoundationAddress.Value,
                    Amount = amount,
                    Symbol = Context.Variables.NativeSymbol,
                });
            }
            State.OwedToFoundation.Value = owed.Sub(amount);
            return(new Empty());
        }
        public override Empty Deposit(SInt64Value input)
        {
            var information = State.PlayerInformation[Context.Sender];

            Assert(information != null, "Not registered.");
            State.TokenContract.TransferFrom.Send(new TransferFromInput
            {
                Symbol = Context.Variables.NativeSymbol,
                Amount = input.Value,
                From   = Context.Sender,
                // TODO: Created a profit item and To = ProfitItemVirtualAddress
                To   = Context.Self,
                Memo = "Thanks for recharging."
            });
            State.TokenContract.Transfer.Send(new TransferInput
            {
                Symbol = BingoGameContractConstants.CardSymbol,
                Amount = input.Value,
                To     = Context.Sender,
                Memo   = "Now you are stronger."
            });

            return(new Empty());
        }
Пример #18
0
 public override Round GetRoundInformation(SInt64Value input) =>
 TryToGetRoundInformation(input.Value, out var round) ? round : new Round();
Пример #19
0
 /// <summary>
 /// Get total weights of a specific term.
 /// </summary>
 /// <param name="input"></param>
 /// <returns></returns>
 public override SInt64Value GetTermTotalWeights(SInt64Value input)
 {
     return(new SInt64Value {
         Value = State.TotalWeightsMap[input.Value]
     });
 }
Пример #20
0
        public override IndexedSideChainBlockData GetIndexedSideChainBlockDataByHeight(SInt64Value input)
        {
            var indexedSideChainBlockData = State.IndexedSideChainBlockData[input.Value];

            return(indexedSideChainBlockData ?? new IndexedSideChainBlockData());
        }
Пример #21
0
 public override TermSnapshot GetTermSnapshot(SInt64Value input)
 {
     return(State.SnapshotMap[input.Value.ToInt64Value()]);
 }
Пример #22
0
 public override Round GetRoundInformation(SInt64Value input)
 {
     return(TryToGetRoundInformation(input.Value, out var roundInfo) ? roundInfo : null);
 }
Пример #23
0
 /// <summary>
 /// Get dividends of a specific term.
 /// </summary>
 /// <param name="input"></param>
 /// <returns></returns>
 public override SInt64Value GetTermDividends(SInt64Value input)
 {
     return(new SInt64Value {
         Value = State.DividendsMap[input.Value]
     });
 }
Пример #24
0
        public override CrossChainMerkleProofContext GetBoundParentChainHeightAndMerklePathByHeight(SInt64Value input)
        {
            var boundParentChainHeight = State.ChildHeightToParentChainHeight[input.Value];

            Assert(boundParentChainHeight != 0);
            var merklePath = State.TxRootMerklePathInParentChain[input.Value];

            Assert(merklePath != null);
            return(new CrossChainMerkleProofContext
            {
                MerklePathForParentChainRoot = merklePath,
                BoundParentChainHeight = boundParentChainHeight
            });
        }
Пример #25
0
        public override IndexedSideChainBlockData GetIndexedSideChainBlockDataByHeight(SInt64Value input)
        {
            var indexedSideChainBlockData = State.IndexedSideChainBlockData[input.Value];

            Assert(indexedSideChainBlockData != null, "Side chain block data should not be null.");
            return(indexedSideChainBlockData);
        }