From 9325aaf1ca899ebe065085b2fd21da36f925f564 Mon Sep 17 00:00:00 2001 From: Shahar Yakir Date: Thu, 5 Dec 2024 10:55:23 +0000 Subject: [PATCH 1/2] logger + tact 1.5.3 --- package-lock.json | 392 +++++++++++++++++++- package.json | 6 +- src/controller.ts | 5 +- src/logger.ts | 179 +++++++++ src/server.ts | 10 +- src/source-verifier/fift-source-verifier.ts | 5 +- src/source-verifier/tact-source-verifier.ts | 31 +- 7 files changed, 609 insertions(+), 19 deletions(-) create mode 100644 src/logger.ts diff --git a/package-lock.json b/package-lock.json index 325e7c0..38a8d7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "ipfs-utils": "^9.0.14", "mkdirp": "^1.0.4", "multer": "^1.4.5-lts.1", + "randomstring": "^1.3.0", "tact-1.0.0": "npm:@tact-lang/compiler@1.0.0", "tact-1.1.0": "npm:@tact-lang/compiler@1.1.0", "tact-1.1.1": "npm:@tact-lang/compiler@1.1.1", @@ -41,12 +42,14 @@ "tact-1.5.0": "npm:@tact-lang/compiler@1.5.0", "tact-1.5.1": "npm:@tact-lang/compiler@1.5.1", "tact-1.5.2": "npm:@tact-lang/compiler@1.5.2", + "tact-1.5.3": "npm:@tact-lang/compiler@1.5.3", "ton": "^13.4.1", "ton-core": "^0.49.0", "ts-node": "^10.9.1", "ts-sinon": "^2.0.2", "tweetnacl": "^1.0.3", - "typescript": "^4.8.4" + "typescript": "^4.8.4", + "winston": "^3.17.0" }, "devDependencies": { "@types/async": "^3.2.16", @@ -57,6 +60,7 @@ "@types/mkdirp": "^1.0.2", "@types/multer": "^1.4.7", "@types/node": "^16.11.45", + "@types/randomstring": "^1.3.0", "@types/semver": "^7.5.8", "husky": "^8.0.0", "jest-mock-extended": "^2.0.7", @@ -1659,6 +1663,15 @@ "dev": true, "peer": true }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -1679,6 +1692,17 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "license": "MIT", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@ipld/dag-cbor": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-7.0.2.tgz", @@ -2859,6 +2883,13 @@ "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", "dev": true }, + "node_modules/@types/randomstring": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@types/randomstring/-/randomstring-1.3.0.tgz", + "integrity": "sha512-kCP61wludjY7oNUeFiMxfswHB3Wn/aC03Cu82oQsNTO6OCuhVN/rCbBs68Cq6Nkgjmp2Sh3Js6HearJPkk7KQA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", @@ -2910,6 +2941,12 @@ "dev": true, "peer": true }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" + }, "node_modules/@types/yargs": { "version": "17.0.10", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", @@ -3762,6 +3799,16 @@ "dev": true, "peer": true }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -3775,6 +3822,26 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "license": "MIT", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -4177,6 +4244,12 @@ "dev": true, "peer": true }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -4461,6 +4534,12 @@ "bser": "2.1.1" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -4521,6 +4600,12 @@ "node": ">=8" } }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "license": "MIT" + }, "node_modules/follow-redirects": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", @@ -5316,8 +5401,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "peer": true, "engines": { "node": ">=8" }, @@ -7324,6 +7407,12 @@ "node": ">=6" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -7366,6 +7455,23 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -8020,6 +8126,15 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -8398,6 +8513,27 @@ "node": ">= 6" } }, + "node_modules/randombytes": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.3.tgz", + "integrity": "sha512-lDVjxQQFoCG1jcrP06LNo2lbWp4QTShEXnhActFBwYuHprllQV6VUpwreApsYqCgD+N1mHoqJ/BI/4eV4R2GYg==", + "license": "MIT" + }, + "node_modules/randomstring": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/randomstring/-/randomstring-1.3.0.tgz", + "integrity": "sha512-gY7aQ4i1BgwZ8I1Op4YseITAyiDiajeZOPQUbIq9TPGPhUm5FX59izIaOpmKbME1nmnEiABf28d9K2VSii6BBg==", + "license": "MIT", + "dependencies": { + "randombytes": "2.0.3" + }, + "bin": { + "randomstring": "bin/randomstring" + }, + "engines": { + "node": "*" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -8692,6 +8828,15 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -8843,6 +8988,21 @@ "dev": true, "peer": true }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" + }, "node_modules/sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -8984,6 +9144,15 @@ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -11453,6 +11622,144 @@ "multiformats": "^9.4.2" } }, + "node_modules/tact-1.5.3": { + "name": "@tact-lang/compiler", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@tact-lang/compiler/-/compiler-1.5.3.tgz", + "integrity": "sha512-BxSCWfIQJUa0RC2ZltYfgTeN+3dRjMs4Hdxq61REfghpRiSU0IKdkLPGqJH/5zimzFFhjD4mhR0aFS71zUH9hA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@tact-lang/opcode": "^0.0.16", + "@ton/core": "0.58.1", + "@ton/crypto": "^3.2.0", + "blockstore-core": "1.0.5", + "change-case": "^4.1.2", + "crc-32": "1.2.2", + "ipfs-unixfs-importer": "9.0.10", + "json-bigint": "^1.0.0", + "meow": "^13.2.0", + "mkdirp": "^2.1.3", + "ohm-js": "^17.1.0", + "path-normalize": "^6.0.13", + "prando": "^6.0.1", + "zod": "^3.22.4" + }, + "bin": { + "tact": "bin/tact.js" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/tact-1.5.3/node_modules/@tact-lang/opcode": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@tact-lang/opcode/-/opcode-0.0.16.tgz", + "integrity": "sha512-YJTUjoDOy+e+FHHppJiF+uWJ2IMjVknB9VQ5n78pknCE129DazCb/nFXnw0wVRDVcn8Tn59ky+pmjiQjQOjEbw==", + "license": "MIT", + "peerDependencies": { + "@ton/core": ">=0.49.2", + "@ton/crypto": "^3.2.0" + } + }, + "node_modules/tact-1.5.3/node_modules/@ton/core": { + "version": "0.58.1", + "resolved": "https://registry.npmjs.org/@ton/core/-/core-0.58.1.tgz", + "integrity": "sha512-zydh42iT6E3U3Ky/DhTFqJMN/ycKKzbsHASY257Qr2sZn97G/MOcHFizPfMnbJJgx0H9iHX6mdyMvp1IKBVAFA==", + "license": "MIT", + "dependencies": { + "symbol.inspect": "1.0.1" + }, + "peerDependencies": { + "@ton/crypto": ">=3.2.0" + } + }, + "node_modules/tact-1.5.3/node_modules/ipfs-unixfs": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/ipfs-unixfs/-/ipfs-unixfs-6.0.9.tgz", + "integrity": "sha512-0DQ7p0/9dRB6XCb0mVCTli33GzIzSVx5udpJuVM47tGcD+W+Bl4LsnoLswd3ggNnNEakMv1FdoFITiEnchXDqQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "err-code": "^3.0.1", + "protobufjs": "^6.10.2" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/tact-1.5.3/node_modules/ipfs-unixfs-importer": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/ipfs-unixfs-importer/-/ipfs-unixfs-importer-9.0.10.tgz", + "integrity": "sha512-W+tQTVcSmXtFh7FWYWwPBGXJ1xDgREbIyI1E5JzDcimZLIyT5gGMfxR3oKPxxWj+GKMpP5ilvMQrbsPzWcm3Fw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@ipld/dag-pb": "^2.0.2", + "@multiformats/murmur3": "^1.0.3", + "bl": "^5.0.0", + "err-code": "^3.0.1", + "hamt-sharding": "^2.0.0", + "interface-blockstore": "^2.0.3", + "ipfs-unixfs": "^6.0.0", + "it-all": "^1.0.5", + "it-batch": "^1.0.8", + "it-first": "^1.0.6", + "it-parallel-batch": "^1.0.9", + "merge-options": "^3.0.4", + "multiformats": "^9.4.2", + "rabin-wasm": "^0.1.4", + "uint8arrays": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/tact-1.5.3/node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tact-1.5.3/node_modules/mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tact-1.5.3/node_modules/ohm-js": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/ohm-js/-/ohm-js-17.1.0.tgz", + "integrity": "sha512-xc3B5dgAjTBQGHaH7B58M2Pmv6WvzrJ/3/7LeUzXNg0/sY3jQPdSd/S2SstppaleO77rifR1tyhdfFGNIwxf2Q==", + "license": "MIT", + "engines": { + "node": ">=0.12.1" + } + }, + "node_modules/tact-1.5.3/node_modules/uint8arrays": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", + "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -11490,6 +11797,12 @@ "node": ">=8" } }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "license": "MIT" + }, "node_modules/timeout-abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz", @@ -11592,6 +11905,15 @@ "node": ">=8" } }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-essentials": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", @@ -12056,6 +12378,70 @@ "node": ">= 8" } }, + "node_modules/winston": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", + "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "license": "MIT", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 683b843..128900a 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "ipfs-utils": "^9.0.14", "mkdirp": "^1.0.4", "multer": "^1.4.5-lts.1", + "randomstring": "^1.3.0", "tact-1.0.0": "npm:@tact-lang/compiler@1.0.0", "tact-1.1.0": "npm:@tact-lang/compiler@1.1.0", "tact-1.1.1": "npm:@tact-lang/compiler@1.1.1", @@ -36,12 +37,14 @@ "tact-1.5.0": "npm:@tact-lang/compiler@1.5.0", "tact-1.5.1": "npm:@tact-lang/compiler@1.5.1", "tact-1.5.2": "npm:@tact-lang/compiler@1.5.2", + "tact-1.5.3": "npm:@tact-lang/compiler@1.5.3", "ton": "^13.4.1", "ton-core": "^0.49.0", "ts-node": "^10.9.1", "ts-sinon": "^2.0.2", "tweetnacl": "^1.0.3", - "typescript": "^4.8.4" + "typescript": "^4.8.4", + "winston": "^3.17.0" }, "scripts": { "__prebuild": "tslint -p tsconfig.json --fix", @@ -60,6 +63,7 @@ "@types/mkdirp": "^1.0.2", "@types/multer": "^1.4.7", "@types/node": "^16.11.45", + "@types/randomstring": "^1.3.0", "@types/semver": "^7.5.8", "husky": "^8.0.0", "jest-mock-extended": "^2.0.7", diff --git a/src/controller.ts b/src/controller.ts index a891f1e..03695b1 100644 --- a/src/controller.ts +++ b/src/controller.ts @@ -21,9 +21,12 @@ import { verifierRegistryForwardMessage, } from "./cell-builders"; import mkdirp from "mkdirp"; +import { getLogger } from "./logger"; export type Base64URL = string; +const logger = getLogger("controller"); + interface ControllerConfig { verifierId: string; privateKey: string; @@ -113,7 +116,7 @@ export class Controller { true, ); - console.log(ipfsLink); + logger.info(ipfsLink); const queryId = random64BitNumber(); diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000..07d6471 --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,179 @@ +import winston, { format, LoggerModified, LoggerOptions } from "winston"; + +import { AsyncLocalStorage } from "async_hooks"; +import { randomUUID } from "crypto"; +import randomstring from "randomstring"; + +const asyncLocalStorage = new AsyncLocalStorage>(); +const globalContext = new Map(); + +declare module "winston" { + interface LoggerModified { + debug: Logger["debug"]; + info: Logger["info"]; + warn: Logger["warn"]; + error: Logger["error"]; + + addToContext: (entries: { [key: string]: unknown }) => LoggerModified; + addToGlobalContext: (entries: { [key: string]: unknown }) => LoggerModified; + + debugSampled: (rate: number, message: unknown, ...args: unknown[]) => LoggerModified; + } +} + +const instanceId = randomstring.generate(6); + +const customLevels = { + levels: { + critical: 0, + error: 1, + warn: 2, + info: 3, + debug: 4, + }, +}; + +export function getLogger( + module: string, + meta: Record = {}, + level: string = "debug", +) { + const defaultMeta: LoggerOptions["defaultMeta"] = { + module, + instanceId, + }; + + const addMetaAndStack = winston.format.printf((info) => { + info.meta = (info[Symbol.for("splat")] as unknown[])?.[0] ?? {}; + info.meta = { ...(info.meta as any), ...meta }; + + if (info.stack) (info.message as any) += info.stack; + + let stringified = JSON.stringify(info.meta); + delete info.meta; + + if (stringified === "{}") stringified = ""; + return `${info.timestamp} ${info.service} ${module} ${info.level.toUpperCase()} ${ + info.message + } ${stringified}`; + }); + + const _logger = winston.createLogger({ + levels: customLevels.levels, + level, + format: winston.format.combine( + winston.format.timestamp(), + winston.format.errors({ stack: true }), + winston.format.prettyPrint(), + addMetaAndStack, + winston.format((info) => { + info.context = { ...(info.context ?? {}), ...Object.fromEntries(globalContext) }; + const store = asyncLocalStorage.getStore(); + if (!store) return info; + info.context = { ...(info.context as any), ...Object.fromEntries(store.entries()) }; + return info; + })(), + ), + defaultMeta: defaultMeta, + transports: [ + new winston.transports.Console({ + format: process.env.NO_JSON_LOGGING + ? format.printf((info) => { + return `${info[Symbol.for("message")]}`; + }) + : winston.format.json(), + }), + ], + }); + + const logWithStackTrace = (errorCode: string, message: unknown, ...args: unknown[]) => { + let msg = message; + + args[0] = { errorCode, ...(args[0] ?? {}) }; + + if (typeof message === "string") { + const err = new Error(message as never); + // Remove the line coming from the synthetic error created the line above + err.stack = err.stack?.replace(new RegExp(`^\\s+at.*_logger\\.${"error"}.*$\\n`, "m"), ""); + msg = err; + } else if (!(message instanceof Error) && typeof message === "object") { + msg = JSON.stringify(message); + } + + _logger.log("error", msg as never, ...args); + + return _logger; + }; + + // Override logger error to always print stack traces + _logger.error = (message: unknown, ...args: unknown[]) => + logWithStackTrace("error", message, ...args); + + const logger = _logger as unknown as LoggerModified; + + logger.addToContext = (entries: { [key: string]: unknown }) => { + const store = asyncLocalStorage.getStore(); + if (!store) { + logger.error( + "addToContext must be called inside of an async function wrapped in withContext", + { + ...entries, + }, + ); + return logger; + } + + Object.entries(entries).forEach(([key, value]) => store.set(key, value)); + + return logger; + }; + + logger.debugSampled = (rate: number, message: unknown, ...args: unknown[]) => { + if (rate <= 0 || rate > 1) { + logger.warn("sampleOnce rate must be between 0 and 1, ignoring", { rate }); + return logger; + } + + if (Math.random() < rate) { + logger.debug(message as unknown as string, ...args); + } + + return logger; + }; + + logger.addToGlobalContext = (entries: { [key: string]: unknown }) => { + Object.entries(entries).forEach(([key, value]) => globalContext.set(key, value)); + return logger; + }; + + return logger; +} + +export function withContext(fn: () => T) { + let store = asyncLocalStorage.getStore(); + + if (store) { + throw new Error( + "cannot use withContext inside an async function that is already wrapped in withContext", + ); + } + + store = new Map(); + store.set("traceId", randomUUID()); + + return asyncLocalStorage.run(store, fn); +} + +export function hasContext() { + return asyncLocalStorage.getStore() !== undefined; +} + +export function getContext() { + const store = asyncLocalStorage.getStore(); + + if (!store) { + throw new Error("getContext must be called inside of an async function wrapped in withContext"); + } + + return Object.fromEntries(store.entries()); +} diff --git a/src/server.ts b/src/server.ts index 2443f69..b768dfe 100644 --- a/src/server.ts +++ b/src/server.ts @@ -22,6 +22,9 @@ import { TonReaderClientImpl } from "./ton-reader-client"; import { getLatestVerified } from "./latest-known-contracts"; import { DeployController } from "./deploy-controller"; import { getSupportedVersions } from "./fetch-compiler-versions"; +import { getLogger } from "./logger"; + +const logger = getLogger("server"); const app = express(); app.use(idMiddleware()); @@ -212,7 +215,7 @@ app.get("/hc", (req, res) => { }); res.json(result); } catch (e) { - console.error(e.toString()); + logger.error(e); res.status(500).send(e.toString()); } }, @@ -227,14 +230,13 @@ app.get("/hc", (req, res) => { }); app.use(function (err: any, req: any, res: any, next: any) { - console.error(err.message); // Log error message in our server's console + logger.error(err); // Log error message in our server's console if (!err.statusCode) err.statusCode = 500; // If err has no specified error code, set error code to 'Internal Server Error (500)' - console.error(err.stack); res.status(err.statusCode).send(err); // All HTTP requests must have a response, so let's send back an error with its status }); app.listen(port, () => { - console.log( + logger.info( `Ton Contract Verifier Server running on ${port}. Verifier Id: ${process.env.VERIFIER_ID}`, ); }); diff --git a/src/source-verifier/fift-source-verifier.ts b/src/source-verifier/fift-source-verifier.ts index f99af6d..af4d6aa 100644 --- a/src/source-verifier/fift-source-verifier.ts +++ b/src/source-verifier/fift-source-verifier.ts @@ -8,6 +8,9 @@ import { Cell } from "ton"; import { FuncCompilerVersion } from "@ton-community/contract-verifier-sdk"; import { binaryPath } from "../binaries"; import { specialCharsRegex } from "./func-source-verifier"; +import { getLogger } from "../logger"; + +const logger = getLogger("fift-source-verifier"); export async function fiftToCodeCell( funcVersion: FuncCompilerVersion, @@ -61,7 +64,7 @@ export class FiftSourceVerifier implements SourceVerifier { sources, }; } catch (e) { - console.error(e); + logger.error(e); return { hash: null, result: "unknown_error", diff --git a/src/source-verifier/tact-source-verifier.ts b/src/source-verifier/tact-source-verifier.ts index 0d0c3a0..1b29164 100644 --- a/src/source-verifier/tact-source-verifier.ts +++ b/src/source-verifier/tact-source-verifier.ts @@ -7,6 +7,9 @@ import { Cell } from "ton"; import { getSupportedVersions } from "../fetch-compiler-versions"; import { CompileResult, SourceVerifier, SourceVerifyPayload } from "../types"; import { timeoutPromise } from "../utils"; +import { getLogger } from "../logger"; + +const logger = getLogger("tact-source-verifier"); export type FileSystem = { readFile: (path: string) => Promise; @@ -74,7 +77,10 @@ export class TactSourceVerifier implements SourceVerifier { pkgParsed.compiler.parameters = pkgParsed.compiler.parameters?.replace(/\\/g, "/"); } } catch (e) { - console.warn("Unable to replace windows paths in entrypoint. ", pkgParsed.compiler); + logger.error(e); + logger.warn("Unable to replace windows paths in entrypoint. ", { + info: pkgParsed.compiler, + }); } // Fix windows paths (END) @@ -119,22 +125,29 @@ export class TactSourceVerifier implements SourceVerifier { }); } - const v = await timeoutPromise(vPromise, parseInt(process.env.COMPILE_TIMEOUT ?? "3000")); + const verificationResult = await timeoutPromise( + vPromise, + parseInt(process.env.COMPILE_TIMEOUT ?? "3000"), + ); - if (!v.ok) { - console.log(output, "shahar", v.error); - console.error("Failed to compile tact package", output.join("\n")); + if (!verificationResult.ok) { + logger.error("Failed to compile tact package", { + output: output.join("\n"), + verificationResult: verificationResult, + compilerSettings, + }); return { compilerSettings, - error: [v.error, ...output].join("\n"), + error: [verificationResult.error, ...output].join("\n"), hash: null, - result: v.error === "verification-failed" ? "not_similar" : "unknown_error", + result: + verificationResult.error === "verification-failed" ? "not_similar" : "unknown_error", sources: [], }; } const sources = await Promise.all( - Object.entries(v.files) + Object.entries(verificationResult.files) .filter(([filename]) => filename.match(/\.(abi|tact|pkg)$/) && !filename.match(/\.\./)) .map(async ([filename, contentB64]) => { const writePath = path.join(payload.tmpDir, filename); @@ -158,7 +171,7 @@ export class TactSourceVerifier implements SourceVerifier { */ sources.push({ filename: pkgFilePath }); - const compiledHash = Cell.fromBoc(Buffer.from(v.package.code, "base64"))[0] + const compiledHash = Cell.fromBoc(Buffer.from(verificationResult.package.code, "base64"))[0] .hash() .toString("base64"); From ba5e782092fea26d1ee8d036d27d4ce2ef619fa9 Mon Sep 17 00:00:00 2001 From: Shahar Yakir Date: Thu, 5 Dec 2024 11:06:25 +0000 Subject: [PATCH 2/2] more logging --- src/latest-known-contracts.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/latest-known-contracts.ts b/src/latest-known-contracts.ts index d0cea62..a64b004 100644 --- a/src/latest-known-contracts.ts +++ b/src/latest-known-contracts.ts @@ -6,6 +6,7 @@ import { sha256 } from "./utils"; import { getTonClient } from "./ton-reader-client"; import { toBigIntBE } from "bigint-buffer"; import { SourceItem } from "./wrappers/source-item"; +import { getLogger } from "./logger"; dotenv.config({ path: ".env.local" }); dotenv.config({ path: ".env" }); @@ -18,6 +19,8 @@ const contracts: { }[] = []; let lastUpdateTime: null | Date = null; +const logger = getLogger("latest-known-contracts"); + async function update(verifierIdSha256: Buffer, ipfsProvider: string) { // TODO - this means that clients get empty responses quickly instead of waiting // for the single-instance fetch. needsfix @@ -94,7 +97,7 @@ async function update(verifierIdSha256: Buffer, ipfsProvider: string) { compiler: ipfsData.data.compiler, }); } catch (e) { - console.warn(e); + logger.error(e); callback(null); } }, @@ -103,7 +106,7 @@ async function update(verifierIdSha256: Buffer, ipfsProvider: string) { // @ts-ignore contracts.unshift(...results.filter((o: any) => o)); } catch (e) { - console.warn(e); + logger.error(e); lastUpdateTime = null; } }