public static RelayReceipt FromBytes(byte[] bytes) { using (var stream = new MemoryStream(bytes)) { using (var reader = new BinaryReader(stream)) { var receipt = new RelayReceipt(); receipt.UnserializeData(reader); return(receipt); } } }
public void SettleChannel(RelayReceipt receipt) { var channelIndex = GetIndex(receipt.message.sender, receipt.message.receiver); // check for possible replay attack Runtime.Expect(receipt.message.nexus == Runtime.NexusName, "invalid nexus name"); // here we count how many receipts we are implicitly accepting // this means that we don't need to accept every receipt, allowing skipping several var receiptCount = 1 + receipt.message.index - channelIndex; Runtime.Expect(receiptCount > 0, "invalid receipt index"); var expectedFee = RelayFeePerMessage * receiptCount; var balance = GetBalance(receipt.message.sender); Runtime.Expect(balance >= expectedFee, "insuficient balance"); var bytes = receipt.message.ToByteArray(); Runtime.Expect(receipt.signature.Verify(bytes, receipt.message.sender), "invalid signature"); balance -= expectedFee; _balances.Set <Address, BigInteger>(receipt.message.sender, balance); var key = MakeKey(receipt.message.sender, receipt.message.receiver); _indices.Set <string, BigInteger>(key, receipt.message.index + 1); Runtime.Expect(expectedFee > 0, "invalid payout"); var payout = expectedFee / 2; // send half to the chain Runtime.TransferTokens(DomainSettings.FuelTokenSymbol, this.Address, this.Address, payout); // send half to the receiver Runtime.TransferTokens(DomainSettings.FuelTokenSymbol, this.Address, receipt.message.receiver, payout); Runtime.Notify(EventKind.ChannelSettle, receipt.message.sender, receiptCount); }