From 05010d142955f2d5bef25c85dc23949077c83ae6 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Thu, 26 Sep 2024 12:23:29 -0400 Subject: [PATCH 1/4] feat: add enhanced server coin management --- src/blockchain/ServerCoin.ts | 50 +++++++++++++++++++++++++++++++----- src/types.ts | 1 + 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/blockchain/ServerCoin.ts b/src/blockchain/ServerCoin.ts index ccf1428..aa193ff 100644 --- a/src/blockchain/ServerCoin.ts +++ b/src/blockchain/ServerCoin.ts @@ -15,7 +15,7 @@ import { NconfManager } from "../utils/NconfManager"; import { CoinData, ServerCoinData } from "../types"; import { DataStore } from "./DataStore"; import NodeCache from "node-cache"; -import { getPublicIpAddress } from '../utils/network'; +import { getPublicIpAddress } from "../utils/network"; import { Environment } from "../utils/Environment"; const serverCoinCollateral = 300_000_000; @@ -45,7 +45,7 @@ export class ServerCoin { BigInt(1000000) ); - const { epoch: currentEpoch} = ServerCoin.getCurrentEpoch(); + const { epoch: currentEpoch } = ServerCoin.getCurrentEpoch(); const epochBasedHint = morphLauncherId( Buffer.from(this.storeId, "hex"), BigInt(currentEpoch) @@ -185,7 +185,10 @@ export class ServerCoin { ); } - public async getAllEpochPeers(epoch: number, blacklist: string[] = []): Promise { + public async getAllEpochPeers( + epoch: number, + blacklist: string[] = [] + ): Promise { const cacheKey = `serverCoinPeers-${this.storeId}-${epoch}`; // Check if the result is already cached @@ -194,12 +197,18 @@ export class ServerCoin { return cachedPeers; } - const epochBasedHint = morphLauncherId(Buffer.from(this.storeId, "hex"), BigInt(epoch)); + const epochBasedHint = morphLauncherId( + Buffer.from(this.storeId, "hex"), + BigInt(epoch) + ); const peer = await FullNodePeer.connect(); const maxClvmCost = BigInt(11_000_000_000); - const hintedCoinStates = await peer.getHintedCoinStates(epochBasedHint, false); + const hintedCoinStates = await peer.getHintedCoinStates( + epochBasedHint, + false + ); const filteredCoinStates = hintedCoinStates.filter( (coinState) => coinState.coin.amount >= serverCoinCollateral @@ -254,7 +263,7 @@ export class ServerCoin { if (myIp) { blacklist.push(myIp); } - + const serverCoinPeers = await this.getAllEpochPeers(epoch, blacklist); if (Environment.DEBUG) { console.log("Server Coin Peers: ", serverCoinPeers); @@ -279,7 +288,35 @@ export class ServerCoin { (coin) => coin.epoch === currentEpoch ); + const dataStore = DataStore.from(this.storeId); + const rootHistory = await dataStore.getRootHistory(true); + if (existingCoin) { + const lastRoot = _.last(rootHistory); + + // nothing to do + if (lastRoot?.synced && lastRoot?.root_hash === existingCoin.rootHash) { + return; + } + + // everything is fine, lets just update the roothash for tracking + if (lastRoot?.synced && lastRoot?.root_hash !== existingCoin.rootHash) { + existingCoin.rootHash = lastRoot.root_hash; + // Update the conf with the modified server coin + await ServerCoin.serverCoinManager.setConfigValue( + `${this.storeId}:${peerIp}`, + serverCoins + ); + return; + } + + // If not synced, melt the coin, a new one will be created when synced up + // this helps prevent penalties for not having a valid peer registered + await this.melt(currentEpoch, peerIp); + } + + // Don't create a server coin until you're synced up + if (!_.last(rootHistory)?.synced) { return; } @@ -296,6 +333,7 @@ export class ServerCoin { }, createdAt: new Date().toISOString(), epoch: currentEpoch, + rootHash: _.last(rootHistory)?.root_hash || "", }; await FullNodePeer.waitForConfirmation(serverCoin.coin.parentCoinInfo); diff --git a/src/types.ts b/src/types.ts index ebae3f0..4f6ad1d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -58,6 +58,7 @@ export interface ServerCoinData { coin: CoinData; createdAt: string; // ISO date string epoch: number; + rootHash: string; } export interface IncentiveProgramData { From e1207941dfa13763ebdc73c809d5005ef8ac0bdb Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Thu, 26 Sep 2024 12:26:38 -0400 Subject: [PATCH 2/4] chore(release): 0.0.1-alpha.96 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eab93c..86813db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.0.1-alpha.96](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.95...v0.0.1-alpha.96) (2024-09-26) + + +### Features + +* add enhanced server coin management ([05010d1](https://github.com/DIG-Network/dig-chia-sdk/commit/05010d142955f2d5bef25c85dc23949077c83ae6)) + ### [0.0.1-alpha.95](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.94...v0.0.1-alpha.95) (2024-09-26) diff --git a/package-lock.json b/package-lock.json index ac0133b..874f5dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.95", + "version": "0.0.1-alpha.96", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.95", + "version": "0.0.1-alpha.96", "license": "ISC", "dependencies": { "@dignetwork/datalayer-driver": "^0.1.25", diff --git a/package.json b/package.json index e0d1c00..0538f21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.95", + "version": "0.0.1-alpha.96", "description": "", "type": "commonjs", "main": "./dist/index.js", From 2a968b64ac58acb54e00b5c289c7057be253ce5f Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Thu, 26 Sep 2024 12:35:54 -0400 Subject: [PATCH 3/4] feat: add enhanced server coin management --- src/blockchain/ServerCoin.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/blockchain/ServerCoin.ts b/src/blockchain/ServerCoin.ts index aa193ff..016de0d 100644 --- a/src/blockchain/ServerCoin.ts +++ b/src/blockchain/ServerCoin.ts @@ -34,7 +34,7 @@ export class ServerCoin { } // Create a new server coin for the current epoch - public async createForEpoch(peerIp: string): Promise { + public async createForEpoch(peerIp: string, rootHash: string): Promise { try { const peer = await FullNodePeer.connect(); const wallet = await Wallet.load("default"); @@ -74,7 +74,7 @@ export class ServerCoin { if (err.includes("no spendable coins")) { console.log("No coins available. Will try again in 5 seconds..."); await new Promise((resolve) => setTimeout(resolve, 5000)); - return this.createForEpoch(peerIp); + return this.createForEpoch(peerIp, rootHash); } throw new Error(err); } @@ -83,7 +83,8 @@ export class ServerCoin { await this.saveServerCoinData( newServerCoin.serverCoin, currentEpoch, - peerIp + peerIp, + rootHash ); return newServerCoin.serverCoin; @@ -96,7 +97,8 @@ export class ServerCoin { public async saveServerCoinData( serverCoin: ServerCoinDriver, epoch: number, - peerIp: string + peerIp: string, + rootHash: string, ): Promise { const newServerCoinData: ServerCoinData = { coin: { @@ -105,7 +107,8 @@ export class ServerCoin { parentCoinInfo: serverCoin.coin.parentCoinInfo.toString("hex"), }, createdAt: new Date().toISOString(), - epoch: epoch, + epoch, + rootHash, }; const serverCoins = await this.getServerCoinsForStore(peerIp); @@ -290,10 +293,13 @@ export class ServerCoin { const dataStore = DataStore.from(this.storeId); const rootHistory = await dataStore.getRootHistory(true); + const lastRoot = _.last(rootHistory); - if (existingCoin) { - const lastRoot = _.last(rootHistory); + if (!lastRoot) { + throw new Error('Cant get the last root on chain, something is wrong.'); + } + if (existingCoin) { // nothing to do if (lastRoot?.synced && lastRoot?.root_hash === existingCoin.rootHash) { return; @@ -323,7 +329,7 @@ export class ServerCoin { console.log( `No server coin found for epoch ${currentEpoch}. Creating new server coin...` ); - const serverCoin = await this.createForEpoch(peerIp); + const serverCoin = await this.createForEpoch(peerIp, lastRoot?.root_hash); const newServerCoinData: ServerCoinData = { coin: { From c2846f1a55e23eb5a06819975a8b339eb6b1f667 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Thu, 26 Sep 2024 12:36:54 -0400 Subject: [PATCH 4/4] chore(release): 0.0.1-alpha.97 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86813db..66a318b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.0.1-alpha.97](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.96...v0.0.1-alpha.97) (2024-09-26) + + +### Features + +* add enhanced server coin management ([2a968b6](https://github.com/DIG-Network/dig-chia-sdk/commit/2a968b64ac58acb54e00b5c289c7057be253ce5f)) + ### [0.0.1-alpha.96](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.95...v0.0.1-alpha.96) (2024-09-26) diff --git a/package-lock.json b/package-lock.json index 874f5dd..fe3d9e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.96", + "version": "0.0.1-alpha.97", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.96", + "version": "0.0.1-alpha.97", "license": "ISC", "dependencies": { "@dignetwork/datalayer-driver": "^0.1.25", diff --git a/package.json b/package.json index 0538f21..1372858 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.96", + "version": "0.0.1-alpha.97", "description": "", "type": "commonjs", "main": "./dist/index.js",