public void AssertValidSideChainCreationRequest(SideChainCreationRequest sideChainCreationRequest, Address proposer) { var proposedRequest = State.ProposedSideChainCreationRequestState[Context.Sender]; Assert(proposedRequest == null || Context.CurrentBlockTime >= proposedRequest.ExpiredTime, "Request side chain creation failed."); SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); var allowance = State.TokenContract.GetAllowance.Call(new GetAllowanceInput { Owner = proposer, Spender = Context.Self, Symbol = Context.Variables.NativeSymbol }).Allowance; Assert(allowance >= sideChainCreationRequest.LockedTokenAmount, "Allowance not enough."); if (sideChainCreationRequest.IsPrivilegePreserved) { Assert( sideChainCreationRequest.LockedTokenAmount > 0 && sideChainCreationRequest.IndexingPrice >= 0 && sideChainCreationRequest.LockedTokenAmount > sideChainCreationRequest.IndexingPrice && sideChainCreationRequest.SideChainTokenInitialIssueList.Count > 0 && sideChainCreationRequest.SideChainTokenInitialIssueList.All(issue => issue.Amount > 0), "Invalid chain creation request."); AssertValidSideChainTokenInfo(sideChainCreationRequest.SideChainTokenSymbol, sideChainCreationRequest.SideChainTokenName, sideChainCreationRequest.SideChainTokenTotalSupply); AssertValidResourceTokenAmount(sideChainCreationRequest); } }
private void ProposeNewSideChain(SideChainCreationRequest request, Address proposer) { var sideChainLifeTimeController = GetSideChainLifetimeController(); var proposalCreationInput = new CreateProposalBySystemContractInput { ProposalInput = new CreateProposalInput { ContractMethodName = nameof(CreateSideChain), ToAddress = Context.Self, ExpiredTime = Context.CurrentBlockTime.AddSeconds(SideChainCreationProposalExpirationTimePeriod), Params = new CreateSideChainInput { SideChainCreationRequest = request, Proposer = proposer } .ToByteString(), OrganizationAddress = sideChainLifeTimeController.OwnerAddress }, OriginProposer = Context.Sender }; Context.SendInline(sideChainLifeTimeController.ContractAddress, nameof(AuthorizationContractContainer.AuthorizationContractReferenceState .CreateProposalBySystemContract), proposalCreationInput); }
private void LockTokenAndResource(SideChainCreationRequest sideChainInfo, int chainId) { //Api.Assert(request.Proposer.Equals(Api.GetFromAddress()), "Unable to lock token or resource."); // update locked token balance var balance = GetBalance(new GetBalanceInput { Owner = Context.Sender, Symbol = Context.Variables.NativeSymbol }); Assert(balance > 0); TransferFrom(new TransferFromInput { From = Context.Sender, To = Context.Self, Amount = sideChainInfo.LockedTokenAmount, Symbol = Context.Variables.NativeSymbol }); State.IndexingBalance[chainId] = sideChainInfo.LockedTokenAmount; // Todo: enable resource // lock /*foreach (var resourceBalance in sideChainInfo.ResourceBalances) * { * Api.LockResource(resourceBalance.Amount, resourceBalance.Type); * }*/ }
private void CreateSideChainToken(SideChainCreationRequest sideChainCreationRequest, int chainId, Address creator) { if (!sideChainCreationRequest.IsPrivilegePreserved) { return; } // new token needed only for exclusive side chain var sideChainTokenInfo = new SideChainTokenInfo { TokenName = sideChainCreationRequest.SideChainTokenName, Symbol = sideChainCreationRequest.SideChainTokenSymbol, TotalSupply = sideChainCreationRequest.SideChainTokenTotalSupply, Decimals = sideChainCreationRequest.SideChainTokenDecimals, IsBurnable = sideChainCreationRequest.IsSideChainTokenBurnable, IsProfitable = sideChainCreationRequest.IsSideChainTokenProfitable }; SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); State.TokenContract.Create.Send(new CreateInput { TokenName = sideChainTokenInfo.TokenName, Decimals = sideChainTokenInfo.Decimals, IsBurnable = sideChainTokenInfo.IsBurnable, Issuer = creator, IssueChainId = chainId, Symbol = sideChainTokenInfo.Symbol, TotalSupply = sideChainTokenInfo.TotalSupply, IsProfitable = sideChainTokenInfo.IsProfitable }); }
public override Empty RequestSideChainCreation(SideChainCreationRequest input) { AssertValidSideChainCreationRequest(input, Context.Sender); var sideChainCreationRequestState = ProposeNewSideChain(input, Context.Sender); State.ProposedSideChainCreationRequestState[Context.Sender] = sideChainCreationRequestState; return(new Empty()); }
/// <summary> /// Create side chain. It is a proposal result from system address. /// </summary> /// <param name="sideChainCreationRequest"></param> /// <returns></returns> public override SInt32Value CreateSideChain(SideChainCreationRequest sideChainCreationRequest) { // side chain creation should be triggered by organization address from parliament. CheckOwnerAuthority(); Assert(sideChainCreationRequest.LockedTokenAmount > 0 && sideChainCreationRequest.LockedTokenAmount > sideChainCreationRequest.IndexingPrice, "Invalid chain creation request."); var sideChainTokenInfo = new SideChainTokenInfo { TokenName = sideChainCreationRequest.SideChainTokenName, Symbol = sideChainCreationRequest.SideChainTokenSymbol, TotalSupply = sideChainCreationRequest.SideChainTokenTotalSupply, Decimals = sideChainCreationRequest.SideChainTokenDecimals, IsBurnable = sideChainCreationRequest.IsSideChainTokenBurnable }; AssertSideChainTokenInfo(sideChainTokenInfo); State.SideChainSerialNumber.Value = State.SideChainSerialNumber.Value.Add(1); var serialNumber = State.SideChainSerialNumber.Value; int chainId = GetChainId(serialNumber); // lock token and resource CreateSideChainToken(sideChainCreationRequest, sideChainTokenInfo, chainId); var sideChainInfo = new SideChainInfo { Proposer = Context.Origin, SideChainId = chainId, SideChainStatus = SideChainStatus.Active, SideChainCreationRequest = sideChainCreationRequest, CreationTimestamp = Context.CurrentBlockTime, CreationHeightOnParentChain = Context.CurrentHeight }; State.SideChainInfo[chainId] = sideChainInfo; State.CurrentSideChainHeight[chainId] = 0; var initialConsensusInfo = GetCurrentMiners(); State.SideChainInitialConsensusInfo[chainId] = new BytesValue { Value = initialConsensusInfo.ToByteString() }; Context.LogDebug(() => $"Initial miner list for side chain {chainId} :" + string.Join(",", initialConsensusInfo.MinerList.Pubkeys)); Context.LogDebug(() => $"RoundNumber {initialConsensusInfo.RoundNumber}"); Context.Fire(new CreationRequested() { ChainId = chainId, Creator = Context.Origin }); return(new SInt32Value() { Value = chainId }); }
public override Empty RequestSideChainCreation(SideChainCreationRequest input) { Assert(State.ProposedSideChainCreationRequest[Context.Sender] == null, "Request side chain creation failed."); AssertValidSideChainCreationRequest(input, Context.Sender); ProposeNewSideChain(input, Context.Sender); State.ProposedSideChainCreationRequest[Context.Sender] = input; return(new Empty()); }
private void AssertValidResourceTokenAmount(SideChainCreationRequest sideChainCreationRequest) { var resourceTokenMap = sideChainCreationRequest.InitialResourceAmount; foreach (var resourceTokenSymbol in Context.Variables.SymbolListToPayRental) { Assert(resourceTokenMap.ContainsKey(resourceTokenSymbol) && resourceTokenMap[resourceTokenSymbol] > 0, "Invalid side chain resource token request."); } }
private void CreateSideChainToken(SideChainCreationRequest sideChainCreationRequest, SideChainTokenInfo sideChainTokenInfo, int chainId) { TransferFrom(new TransferFromInput { From = Context.Origin, To = Context.Self, Amount = sideChainCreationRequest.LockedTokenAmount, Symbol = Context.Variables.NativeSymbol }); State.IndexingBalance[chainId] = sideChainCreationRequest.LockedTokenAmount; CreateSideChainToken(sideChainTokenInfo, chainId); }
internal SideChainCreationRequest CreateSideChainCreationRequest(long indexingPrice, long lockedTokenAmount, ByteString contractCode, IEnumerable <ResourceTypeBalancePair> resourceTypeBalancePairs = null) { var res = new SideChainCreationRequest { ContractCode = contractCode, IndexingPrice = indexingPrice, LockedTokenAmount = lockedTokenAmount }; // if (resourceTypeBalancePairs != null) // res.ResourceBalances.AddRange(resourceTypeBalancePairs.Select(x => // ResourceTypeBalancePair.Parser.ParseFrom(x.ToByteString()))); return(res); }
protected SideChainCreationRequest CreateSideChainCreationRequest(long indexingPrice, long lockedTokenAmount, ByteString contractCode, IEnumerable <ResourceTypeBalancePair> resourceTypeBalancePairs = null) { var res = new SideChainCreationRequest { ContractCode = contractCode, IndexingPrice = indexingPrice, LockedTokenAmount = lockedTokenAmount }; if (resourceTypeBalancePairs != null) { res.ResourceBalances.AddRange(resourceTypeBalancePairs); } return(res); }
private ChainInitializationData GetChainInitializationData(SideChainInfo sideChainInfo, SideChainCreationRequest sideChainCreationRequest) { SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); var res = new ChainInitializationData { CreationHeightOnParentChain = sideChainInfo.CreationHeightOnParentChain, ChainId = sideChainInfo.SideChainId, Creator = sideChainInfo.Proposer, CreationTimestamp = sideChainInfo.CreationTimestamp, ChainCreatorPrivilegePreserved = sideChainInfo.IsPrivilegePreserved, ParentChainTokenContractAddress = State.TokenContract.Value }; var initialConsensusInfo = GetInitialConsensusInformation(); res.ChainInitializationConsensusInfo = new ChainInitializationConsensusInfo { InitialConsensusData = initialConsensusInfo }; ByteString nativeTokenInformation = GetNativeTokenInfo().ToByteString(); res.NativeTokenInfoData = nativeTokenInformation; ByteString resourceTokenInformation = GetResourceTokenInfo().ToByteString(); res.ResourceTokenInfo = new ResourceTokenInfo { ResourceTokenListData = resourceTokenInformation, InitialResourceAmount = { sideChainCreationRequest.InitialResourceAmount } }; if (IsPrimaryTokenNeeded(sideChainCreationRequest)) { ByteString sideChainTokenInformation = GetTokenInfo(sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenSymbol).ToByteString(); res.ChainPrimaryTokenInfo = new ChainPrimaryTokenInfo { ChainPrimaryTokenData = sideChainTokenInformation, SideChainTokenInitialIssueList = { sideChainCreationRequest.SideChainTokenInitialIssueList }, }; } return(res); }
private void AssertValidSideChainCreationRequest(SideChainCreationRequest sideChainCreationRequest, Address proposer) { var proposedRequest = State.ProposedSideChainCreationRequestState[Context.Sender]; Assert(proposedRequest == null || Context.CurrentBlockTime >= proposedRequest.ExpiredTime, "Request side chain creation failed."); SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); var allowance = State.TokenContract.GetAllowance.Call(new GetAllowanceInput { Owner = proposer, Spender = Context.Self, Symbol = Context.Variables.NativeSymbol }).Allowance; Assert( allowance >= sideChainCreationRequest.LockedTokenAmount, "Allowance not enough."); Assert( sideChainCreationRequest.IndexingPrice >= 0 && sideChainCreationRequest.LockedTokenAmount >= sideChainCreationRequest.IndexingPrice, "Invalid chain creation request."); if (!sideChainCreationRequest.IsPrivilegePreserved) { return; // there is no restriction for non-exclusive side chain creation } AssertValidResourceTokenAmount(sideChainCreationRequest); if (!IsPrimaryTokenNeeded(sideChainCreationRequest)) { return; } // assert primary token to create AssertValidSideChainTokenInfo(sideChainCreationRequest.SideChainTokenCreationRequest); Assert(sideChainCreationRequest.SideChainTokenInitialIssueList.Count > 0 && sideChainCreationRequest.SideChainTokenInitialIssueList.All(issue => issue.Amount > 0), "Invalid side chain token initial issue list."); }
/// <summary> /// Request from normal address to create side chain. /// </summary> /// <param name="input"></param> /// <returns></returns> public override RequestChainCreationOutput RequestChainCreation(SideChainCreationRequest input) { // no need to check authority since invoked in transaction from normal address Assert(input.LockedTokenAmount > 0 && input.LockedTokenAmount > input.IndexingPrice && !input.ContractCode.IsEmpty, "Invalid chain creation request."); State.SideChainSerialNumber.Value = State.SideChainSerialNumber.Value + 1; var serialNumber = State.SideChainSerialNumber.Value; int chainId = ChainHelpers.GetChainId(serialNumber); var info = State.SideChainInfos[chainId]; Assert(info == null, "Chain creation request already exists."); // lock token and resource LockTokenAndResource(input, chainId); // side chain creation proposal Hash proposalId = Propose(RequestChainCreationWaitingPeriod, Context.Self, nameof(CreateSideChain), new SInt32Value { Value = chainId }); // request.ProposalHash = hash; var sideChainInfo = new SideChainInfo { Proposer = Context.Sender, SideChainId = chainId, SideChainStatus = SideChainStatus.Review, SideChainCreationRequest = input }; State.SideChainInfos[chainId] = sideChainInfo; return(new RequestChainCreationOutput { ChainId = chainId, ProposalId = proposalId }); }
private bool IsPrimaryTokenNeeded(SideChainCreationRequest sideChainCreationRequest) { // there won't be new token creation if it is secondary side chain // or the side chain is not exclusive return(sideChainCreationRequest.IsPrivilegePreserved && !IsParentChainExist()); }