Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(handlers): ensure json.encode everything in data and update records #7

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ constants.ANNUAL_PERCENTAGE_FEE = 0.2
constants.ARNS_NAME_DOES_NOT_EXIST_MESSAGE = "Name does not exist in the ArNS Registry!"
constants.ARNS_MAX_UNDERNAME_MESSAGE = "Name has reached undername limit of 10000"
constants.MAX_ALLOWED_UNDERNAMES = 10000
constants.UNDERNAME_LEASE_FEE_PERCENTAGE = 0.001
constants.UNDERNAME_PERMABUY_FEE_PERCENTAGE = 0.005
constants.UNDERNAME_LEASE_FEE_PERCENTAGE = 0.001 -- 0.1%
constants.UNDERNAME_PERMABUY_FEE_PERCENTAGE = 0.005 -- 0.5%
constants.oneYearMs = 31536000 * 1000
constants.gracePeriodMs = 3 * 7 * 24 * 60 * 60 * 1000
constants.maxLeaseLengthYears = 5
Expand Down
4 changes: 4 additions & 0 deletions src/demand.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ end
-- update at the end of the demand if the current timestamp results in a period greater than our current state
function demand.shouldUpdateDemandFactor(currentTimestamp)
local settings = demand.getSettings()
-- if current timestamp is before the start timestamp, return false
if currentTimestamp < DemandFactor.startTimestamp then
return false
end
local calculatedPeriod = math.floor((currentTimestamp - DemandFactor.startTimestamp) / settings.periodLengthMs) + 1
return calculatedPeriod > demand.getCurrentPeriod()
end
Expand Down
121 changes: 92 additions & 29 deletions src/main.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
-- Adjust package.path to include the current directory
local process = { _version = "0.0.1" }
local constants = require("constants")

Name = Name or "Testnet IO"
Ticker = Ticker or "tIO"
Expand All @@ -19,7 +18,7 @@ Vaults = Vaults or {}
GatewayRegistry = GatewayRegistry or {}
NameRegistry = NameRegistry or {}
Epochs = Epochs or {}
LastTickedEpoch = LastTickedEpoch or 0
LastTickedEpochIndex = LastTickedEpochIndex or -1

local utils = require("utils")
local json = require("json")
Expand Down Expand Up @@ -172,7 +171,7 @@ Handlers.add(ActionMap.CreateVault, utils.hasMatchingTag("Action", ActionMap.Cre
ao.send({
Target = msg.From,
Tags = { Action = "Vault-Created-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -221,12 +220,12 @@ Handlers.add(ActionMap.VaultedTransfer, utils.hasMatchingTag("Action", ActionMap
Recipient = msg.Tags.Recipient,
Quantity = msg.Tags.Quantity,
Tags = { Action = "Debit-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
ao.send({
Target = msg.Tags.Recipient,
Tags = { Action = "Vaulted-Credit-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -262,7 +261,7 @@ Handlers.add(ActionMap.ExtendVault, utils.hasMatchingTag("Action", ActionMap.Ext
ao.send({
Target = msg.From,
Tags = { Action = "Vault-Extended-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -298,7 +297,7 @@ Handlers.add(ActionMap.IncreaseVault, utils.hasMatchingTag("Action", ActionMap.I
ao.send({
Target = msg.From,
Tags = { Action = "Vault-Increased-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -348,7 +347,7 @@ Handlers.add(ActionMap.BuyRecord, utils.hasMatchingTag("Action", ActionMap.BuyRe
ao.send({
Target = msg.From,
Tags = { Action = "Buy-Record-Notice", Name = msg.Tags.Name },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -384,7 +383,7 @@ Handlers.add(ActionMap.ExtendLease, utils.hasMatchingTag("Action", ActionMap.Ext
ao.send({
Target = msg.From,
Tags = { Action = "Extend-Lease-Notice", Name = msg.Tags.Name },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -426,7 +425,7 @@ Handlers.add(
ao.send({
Target = msg.From,
Tags = { Action = "Increase-Undername-Limit-Notice", Name = msg.Tags.Name },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end
Expand Down Expand Up @@ -472,7 +471,7 @@ Handlers.add(ActionMap.TokenCost, utils.hasMatchingTag("Action", ActionMap.Token
years = tonumber(msg.Tags.Years) or 1,
quantity = tonumber(msg.Tags.Quantity),
purchaseType = msg.Tags["Purchase-Type"] or "lease",
currentTimestamp = tonumber(msg.Timestamp),
currentTimestamp = tonumber(msg.Timestamp) or tonumber(msg.Tags.Timestamp),
})
if not status then
ao.send({
Expand All @@ -483,8 +482,8 @@ Handlers.add(ActionMap.TokenCost, utils.hasMatchingTag("Action", ActionMap.Token
else
ao.send({
Target = msg.From,
Tags = { Action = "Token-Cost-Notice", TokenCost = tostring(result) },
Data = tostring(json.encode(result)),
Tags = { Action = "Token-Cost-Notice", ["Token-Cost"] = tostring(result) },
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -522,7 +521,7 @@ Handlers.add(ActionMap.JoinNetwork, utils.hasMatchingTag("Action", ActionMap.Joi
ao.send({
Target = msg.From,
Tags = { Action = "Join-Network-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand All @@ -539,7 +538,7 @@ Handlers.add(ActionMap.LeaveNetwork, utils.hasMatchingTag("Action", ActionMap.Le
ao.send({
Target = msg.From,
Tags = { Action = "Leave-Network-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -578,7 +577,7 @@ Handlers.add(
ao.send({
Target = msg.From,
Tags = { Action = "Increase-Operator-Stake-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end
Expand Down Expand Up @@ -617,7 +616,7 @@ Handlers.add(
ao.send({
Target = msg.From,
Tags = { Action = "Decrease-Operator-Stake-Notice" },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end
Expand Down Expand Up @@ -649,13 +648,13 @@ Handlers.add(ActionMap.DelegateStake, utils.hasMatchingTag("Action", ActionMap.D
ao.send({
Target = msg.From,
Tags = { Action = "Invalid-Delegate-Stake-Notice", Error = "Invalid-Delegate-Stake", Message = result },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
else
ao.send({
Target = msg.From,
Tags = { Action = "Delegate-Stake-Notice", Gateway = msg.Tags.Target },
Data = tostring(json.encode(result)),
Data = json.encode(result),
})
end
end)
Expand Down Expand Up @@ -789,38 +788,101 @@ Handlers.add(ActionMap.SaveObservations, utils.hasMatchingTag("Action", ActionMa
end
end)

Handlers.add("Epoch-Settings", utils.hasMatchingTag("Action", "Epoch-Settings"), function(msg)
local epochSettings = epochs.getSettings()
ao.send({
Target = msg.From,
Action = "Epoch-Settings-Notice",
Data = json.encode(epochSettings),
})
end)

-- TICK HANDLER
Handlers.add("tick", utils.hasMatchingTag("Action", "Tick"), function(msg)
local timestamp = tonumber(msg.Timestamp)
-- TODO: how do we make this update atomic so that the state is changed all or nothing (should we?)
local lastTickedEpochIndex = LastTickedEpoch
local currentEpochIndex = epochs.getEpochIndexForTimestamp(timestamp)
local function tickState(timestamp, blockHeight, hashchain)
-- assert this is a write interaction and we have a timetsamp
assert(msg.Timestamp, "Timestamp is required for a tick interaction")
-- tick the things that only require timestamp and don't need to happen for every epoch
local function tickState(timestamp)
arns.pruneRecords(timestamp)
arns.pruneReservedNames(timestamp)
vaults.pruneVaults(timestamp)
gar.pruneGateways(timestamp)
end

local previousState = {
Balances = utils.deepCopy(Balances),
Vaults = utils.deepCopy(Vaults),
GatewayRegistry = utils.deepCopy(GatewayRegistry),
NameRegistry = utils.deepCopy(NameRegistry),
Epochs = utils.deepCopy(Epochs),
DemandFactor = utils.deepCopy(DemandFactor),
LastTickedEpochIndex = utils.deepCopy(LastTickedEpochIndex),
}
local msgTimestamp = tonumber(msg.Timestamp)

-- tick the state and demand factor using just the timestamp
local stateStatus, stateResult = pcall(tickState, msgTimestamp)
if not stateStatus then
-- reset the state to previous state
Balances = previousState.Balances
Vaults = previousState.Vaults
GatewayRegistry = previousState.GatewayRegistry
NameRegistry = previousState.NameRegistry
Epochs = previousState.Epochs
DemandFactor = previousState.DemandFactor
LastTickedEpochIndex = previousState.LastTickedEpochIndex
ao.send({
Target = msg.From,
Action = "Invalid-Tick-Notice",
Error = "Invalid-Tick",
Data = json.encode(stateResult),
})
end

-- tick and distribute rewards for every index between the last ticked epoch and the current epoch
local function tickEpochs(timestamp, blockHeight, hashchain)
-- update demand factor if necessary
demand.updateDemandFactor(timestamp)
epochs.distributeRewardsForEpoch(timestamp)
epochs.createEpoch(timestamp, tonumber(blockHeight), hashchain)
end

local lastTickedEpochIndex = LastTickedEpochIndex
local currentEpochIndex = epochs.getEpochIndexForTimestamp(msgTimestamp)
-- if epoch index is -1 then we are before the genesis epoch and we should not tick
if currentEpochIndex < 0 then
ao.send({
Target = msg.From,
Action = "Invalid-Tick-Notice",
Error = "Invalid-Tick",
Data = json.encode("Cannot tick before genesis epoch"),
})
end

-- tick and distribute rewards for every index between the last ticked epoch and the current epoch
for i = lastTickedEpochIndex + 1, currentEpochIndex - 1 do
for i = lastTickedEpochIndex + 1, currentEpochIndex do
local previousState = {
Balances = utils.deepCopy(Balances),
Vaults = utils.deepCopy(Vaults),
GatewayRegistry = utils.deepCopy(GatewayRegistry),
NameRegistry = utils.deepCopy(NameRegistry),
Epochs = utils.deepCopy(Epochs),
DemandFactor = utils.deepCopy(DemandFactor),
LastTickedEpochIndex = utils.deepCopy(LastTickedEpochIndex),
}
local _, _, epochDistributionTimestamp = epochs.getEpochTimestampsForIndex(i)
-- TODO: if we need to "recover" epochs, we can't rely on just the current message hashchain and block height
local status, result = pcall(tickState, epochDistributionTimestamp, msg["Block-Height"], msg["Hash-Chain"])
-- use the minimum of the msg timestamp or the epoch distribution timestamp, this ensures an epoch gets created for the genesis block and that we don't try and distribute before an epoch is created
local tickTimestamp = math.min(msgTimestamp or 0, epochDistributionTimestamp)
-- TODO: if we need to "recover" epochs, we can't rely on just the current message hashchain and block height, we should set the prescribed observers and names to empty arrays and distribute rewards accordingly
local status, result = pcall(tickEpochs, tickTimestamp, msg["Block-Height"], msg["Hash-Chain"])
if status then
ao.send({ Target = msg.From, Action = "Tick-Notice", Data = json.encode(result) })
LastTickedEpoch = i -- update the last ticked state
LastTickedEpochIndex = i -- update the last ticked state
ao.send({
Target = msg.From,
Action = "Tick-Notice",
LastTickedEpochIndex = LastTickedEpochIndex,
Data = json.encode(result),
})
else
-- reset the state to previous state
Balances = previousState.Balances
Expand All @@ -829,6 +891,7 @@ Handlers.add("tick", utils.hasMatchingTag("Action", "Tick"), function(msg)
NameRegistry = previousState.NameRegistry
Epochs = previousState.Epochs
DemandFactor = previousState.DemandFactor
LastTickedEpochIndex = previousState.LastTickedEpochIndex
ao.send({
Target = msg.From,
Action = "Invalid-Tick-Notice",
Expand Down
Loading