Compare commits
	
		
			103 Commits
		
	
	
		
			ba94d1563d
			...
			main-22aug
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8fe2af1876 | |||
| a9ee8e1f80 | |||
| e7f4bb6a35 | |||
| 7ce0926d91 | |||
| 3f49993f6b | |||
| ed2229b139 | |||
| 79e7e1a89b | |||
| a19b22f2c0 | |||
| 25dcd27c69 | |||
| dcd3a62e3d | |||
| de8757d59f | |||
| 4e1804bb06 | |||
| e1af79bac9 | |||
| 20a4e9cfd4 | |||
| a80854253a | |||
| 1b7795f038 | |||
| 6495b95c8d | |||
| 63e27f31ac | |||
| 64d57407e0 | |||
| e40e14dea5 | |||
| b988582553 | |||
| 22ce6c07c3 | |||
| 834ddb4438 | |||
| 7e8587660d | |||
| 6b431823f5 | |||
| 82e6047e86 | |||
| 15f277057e | |||
| 04d44aeadf | |||
| b006ea31b0 | |||
| 04efc25a48 | |||
| cccbc07db1 | |||
| 7d5889553d | |||
| 34776214d6 | |||
| 0cc12c5446 | |||
| 57c8b81c13 | |||
| 382a910856 | |||
| a0d2e74115 | |||
| c1f23386b5 | |||
| e5a0eef020 | |||
| c95fce1b69 | |||
| cd119be631 | |||
| a5a27829de | |||
| 246e073092 | |||
| 43dbcd0a17 | |||
| c062ad8e66 | |||
| da56ef57f0 | |||
| b89e6c20ce | |||
| b93e5f890a | |||
| 625a8f71ae | |||
| 8acb4768e3 | |||
| b9d966ff90 | |||
| 1e38b5aca6 | |||
| 3abc4e0a81 | |||
| 49c13d9e42 | |||
| 4e50ee554b | |||
| f5706ac887 | |||
| da787935df | |||
| 77a5f1a071 | |||
| 8425114abf | |||
| 92f6cdcd40 | |||
| f2cce2f592 | |||
| 5d8a2cfdd6 | |||
| 4c0268823b | |||
| bbd1de0020 | |||
| 3a2847295a | |||
| 671c7a4507 | |||
| e0913ece08 | |||
| 1a775c6b87 | |||
| 26323e9c41 | |||
| a79bdc94d0 | |||
| 272ee7522b | |||
| e85f0b987e | |||
| 7eab098a99 | |||
| c0502193b2 | |||
| 9be7df6bcf | |||
| 8183934d09 | |||
| 1558f60810 | |||
| 138fcfc321 | |||
| 153ccfd4db | |||
| eaceb3ecfa | |||
| c0fd0330af | |||
| fc49f06d75 | |||
| 17702b1396 | |||
| aedfc0374b | |||
| bf45c32758 | |||
| 8ee55c5172 | |||
| 65ffe60540 | |||
| 83bcb52887 | |||
| 017d055aaa | |||
| 99eb3ed087 | |||
| 6d1f826e42 | |||
| 781cb24d36 | |||
| fc0ab5feb5 | |||
| a6ea49764e | |||
| 9300121088 | |||
| 4b14b6d51b | |||
| 552641d06c | |||
| 0612b4800f | |||
| 19825d5561 | |||
| f6bcbb181e | |||
| 1fc54cf829 | |||
| d2ae25aaed | |||
| 261871db75 | 
							
								
								
									
										836
									
								
								0x8d871ef2826ac9001fb2e33fdd6379b6aabf449c_abi.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										836
									
								
								0x8d871ef2826ac9001fb2e33fdd6379b6aabf449c_abi.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,836 @@ | ||||
| [ | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "cooldownStart", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "CooldownActive", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "GasLimitExceeded", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "GasPriceExceeded", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "IntervalCompleted", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "IntervalMismatch", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "enum Manager.NodeStatus", | ||||
|                 "name": "status", | ||||
|                 "type": "uint8" | ||||
|             } | ||||
|         ], | ||||
|         "name": "NodeNotActivateable", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "NodeNotActive", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "node", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "enum Manager.NodeStatus", | ||||
|                 "name": "status", | ||||
|                 "type": "uint8" | ||||
|             } | ||||
|         ], | ||||
|         "name": "NodeNotRegisterable", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "NodeRespondedAlready", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "NotSubscriptionOwner", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "SignatureExpired", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "SignerMismatch", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "SubscriptionCompleted", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "SubscriptionNotActive", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "SubscriptionNotFound", | ||||
|         "type": "error" | ||||
|     }, | ||||
|     { | ||||
|         "anonymous": false, | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "indexed": true, | ||||
|                 "internalType": "address", | ||||
|                 "name": "node", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "NodeActivated", | ||||
|         "type": "event" | ||||
|     }, | ||||
|     { | ||||
|         "anonymous": false, | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "indexed": true, | ||||
|                 "internalType": "address", | ||||
|                 "name": "node", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "NodeDeactivated", | ||||
|         "type": "event" | ||||
|     }, | ||||
|     { | ||||
|         "anonymous": false, | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "indexed": true, | ||||
|                 "internalType": "address", | ||||
|                 "name": "node", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "indexed": true, | ||||
|                 "internalType": "address", | ||||
|                 "name": "registerer", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "indexed": false, | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "cooldownStart", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "NodeRegistered", | ||||
|         "type": "event" | ||||
|     }, | ||||
|     { | ||||
|         "anonymous": false, | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "indexed": true, | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "id", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "SubscriptionCancelled", | ||||
|         "type": "event" | ||||
|     }, | ||||
|     { | ||||
|         "anonymous": false, | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "indexed": true, | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "id", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "SubscriptionCreated", | ||||
|         "type": "event" | ||||
|     }, | ||||
|     { | ||||
|         "anonymous": false, | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "indexed": true, | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "id", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "indexed": true, | ||||
|                 "internalType": "address", | ||||
|                 "name": "node", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "SubscriptionFulfilled", | ||||
|         "type": "event" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "DELEGATEE_OVERHEAD_CACHED_WEI", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "DELEGATEE_OVERHEAD_CREATE_WEI", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "DELIVERY_OVERHEAD_WEI", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "EIP712_NAME", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "string", | ||||
|                 "name": "", | ||||
|                 "type": "string" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "EIP712_VERSION", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "string", | ||||
|                 "name": "", | ||||
|                 "type": "string" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "activateNode", | ||||
|         "outputs": [], | ||||
|         "stateMutability": "nonpayable", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "subscriptionId", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "cancelSubscription", | ||||
|         "outputs": [], | ||||
|         "stateMutability": "nonpayable", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "cooldown", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "", | ||||
|                 "type": "uint256" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "string", | ||||
|                 "name": "containerId", | ||||
|                 "type": "string" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes", | ||||
|                 "name": "inputs", | ||||
|                 "type": "bytes" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint48", | ||||
|                 "name": "maxGasPrice", | ||||
|                 "type": "uint48" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "maxGasLimit", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "frequency", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "period", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint16", | ||||
|                 "name": "redundancy", | ||||
|                 "type": "uint16" | ||||
|             } | ||||
|         ], | ||||
|         "name": "createSubscription", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "nonpayable", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "nonce", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "expiry", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "components": [ | ||||
|                     { | ||||
|                         "internalType": "address", | ||||
|                         "name": "owner", | ||||
|                         "type": "address" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint32", | ||||
|                         "name": "activeAt", | ||||
|                         "type": "uint32" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint32", | ||||
|                         "name": "period", | ||||
|                         "type": "uint32" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint32", | ||||
|                         "name": "frequency", | ||||
|                         "type": "uint32" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint16", | ||||
|                         "name": "redundancy", | ||||
|                         "type": "uint16" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint48", | ||||
|                         "name": "maxGasPrice", | ||||
|                         "type": "uint48" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint32", | ||||
|                         "name": "maxGasLimit", | ||||
|                         "type": "uint32" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "string", | ||||
|                         "name": "containerId", | ||||
|                         "type": "string" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "bytes", | ||||
|                         "name": "inputs", | ||||
|                         "type": "bytes" | ||||
|                     } | ||||
|                 ], | ||||
|                 "internalType": "struct Coordinator.Subscription", | ||||
|                 "name": "sub", | ||||
|                 "type": "tuple" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint8", | ||||
|                 "name": "v", | ||||
|                 "type": "uint8" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes32", | ||||
|                 "name": "r", | ||||
|                 "type": "bytes32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes32", | ||||
|                 "name": "s", | ||||
|                 "type": "bytes32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "createSubscriptionDelegatee", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bool", | ||||
|                 "name": "", | ||||
|                 "type": "bool" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "nonpayable", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "deactivateNode", | ||||
|         "outputs": [], | ||||
|         "stateMutability": "nonpayable", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "bytes32", | ||||
|                 "name": "", | ||||
|                 "type": "bytes32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "delegateCreatedIds", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "subscriptionId", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "deliveryInterval", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes", | ||||
|                 "name": "input", | ||||
|                 "type": "bytes" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes", | ||||
|                 "name": "output", | ||||
|                 "type": "bytes" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes", | ||||
|                 "name": "proof", | ||||
|                 "type": "bytes" | ||||
|             } | ||||
|         ], | ||||
|         "name": "deliverCompute", | ||||
|         "outputs": [], | ||||
|         "stateMutability": "nonpayable", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "nonce", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "expiry", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "components": [ | ||||
|                     { | ||||
|                         "internalType": "address", | ||||
|                         "name": "owner", | ||||
|                         "type": "address" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint32", | ||||
|                         "name": "activeAt", | ||||
|                         "type": "uint32" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint32", | ||||
|                         "name": "period", | ||||
|                         "type": "uint32" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint32", | ||||
|                         "name": "frequency", | ||||
|                         "type": "uint32" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint16", | ||||
|                         "name": "redundancy", | ||||
|                         "type": "uint16" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint48", | ||||
|                         "name": "maxGasPrice", | ||||
|                         "type": "uint48" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "uint32", | ||||
|                         "name": "maxGasLimit", | ||||
|                         "type": "uint32" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "string", | ||||
|                         "name": "containerId", | ||||
|                         "type": "string" | ||||
|                     }, | ||||
|                     { | ||||
|                         "internalType": "bytes", | ||||
|                         "name": "inputs", | ||||
|                         "type": "bytes" | ||||
|                     } | ||||
|                 ], | ||||
|                 "internalType": "struct Coordinator.Subscription", | ||||
|                 "name": "sub", | ||||
|                 "type": "tuple" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint8", | ||||
|                 "name": "v", | ||||
|                 "type": "uint8" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes32", | ||||
|                 "name": "r", | ||||
|                 "type": "bytes32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes32", | ||||
|                 "name": "s", | ||||
|                 "type": "bytes32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "deliveryInterval", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes", | ||||
|                 "name": "input", | ||||
|                 "type": "bytes" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes", | ||||
|                 "name": "output", | ||||
|                 "type": "bytes" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes", | ||||
|                 "name": "proof", | ||||
|                 "type": "bytes" | ||||
|             } | ||||
|         ], | ||||
|         "name": "deliverComputeDelegatee", | ||||
|         "outputs": [], | ||||
|         "stateMutability": "nonpayable", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "eip712Domain", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "bytes1", | ||||
|                 "name": "fields", | ||||
|                 "type": "bytes1" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "string", | ||||
|                 "name": "name", | ||||
|                 "type": "string" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "string", | ||||
|                 "name": "version", | ||||
|                 "type": "string" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint256", | ||||
|                 "name": "chainId", | ||||
|                 "type": "uint256" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "verifyingContract", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes32", | ||||
|                 "name": "salt", | ||||
|                 "type": "bytes32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint256[]", | ||||
|                 "name": "extensions", | ||||
|                 "type": "uint256[]" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "activeAt", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "period", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "getSubscriptionInterval", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [], | ||||
|         "name": "id", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "maxSubscriberNonce", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "nodeInfo", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "enum Manager.NodeStatus", | ||||
|                 "name": "status", | ||||
|                 "type": "uint8" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "cooldownStart", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "bytes32", | ||||
|                 "name": "", | ||||
|                 "type": "bytes32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "nodeResponded", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "bool", | ||||
|                 "name": "", | ||||
|                 "type": "bool" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "bytes32", | ||||
|                 "name": "", | ||||
|                 "type": "bytes32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "redundancyCount", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "uint16", | ||||
|                 "name": "", | ||||
|                 "type": "uint16" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "node", | ||||
|                 "type": "address" | ||||
|             } | ||||
|         ], | ||||
|         "name": "registerNode", | ||||
|         "outputs": [], | ||||
|         "stateMutability": "nonpayable", | ||||
|         "type": "function" | ||||
|     }, | ||||
|     { | ||||
|         "inputs": [ | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "", | ||||
|                 "type": "uint32" | ||||
|             } | ||||
|         ], | ||||
|         "name": "subscriptions", | ||||
|         "outputs": [ | ||||
|             { | ||||
|                 "internalType": "address", | ||||
|                 "name": "owner", | ||||
|                 "type": "address" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "activeAt", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "period", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "frequency", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint16", | ||||
|                 "name": "redundancy", | ||||
|                 "type": "uint16" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint48", | ||||
|                 "name": "maxGasPrice", | ||||
|                 "type": "uint48" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "uint32", | ||||
|                 "name": "maxGasLimit", | ||||
|                 "type": "uint32" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "string", | ||||
|                 "name": "containerId", | ||||
|                 "type": "string" | ||||
|             }, | ||||
|             { | ||||
|                 "internalType": "bytes", | ||||
|                 "name": "inputs", | ||||
|                 "type": "bytes" | ||||
|             } | ||||
|         ], | ||||
|         "stateMutability": "view", | ||||
|         "type": "function" | ||||
|     } | ||||
| ] | ||||
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @ -15,7 +15,6 @@ build-multiplatform: | ||||
| deploy-container: stop-container | ||||
| 	cp ./projects/$(project)/container/config.json deploy/config.json | ||||
| 	docker compose -f deploy/docker-compose.yaml up -d | ||||
| 	docker logs infernet-node -f | ||||
|  | ||||
| stop-container: | ||||
| 	docker compose -f deploy/docker-compose.yaml kill || true | ||||
|  | ||||
							
								
								
									
										374
									
								
								checker.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								checker.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,374 @@ | ||||
| # flake8: noqa | ||||
| # pylint: disable=broad-exception-raised, raise-missing-from, too-many-arguments, redefined-outer-name | ||||
| # pylance: disable=reportMissingImports, reportMissingModuleSource, reportGeneralTypeIssues | ||||
| # type: ignore | ||||
|  | ||||
| import warnings | ||||
| warnings.filterwarnings("ignore", category=Warning) | ||||
|  | ||||
| import re | ||||
| from datetime import datetime, timedelta, timezone | ||||
| import subprocess | ||||
| import os | ||||
| import time | ||||
| import random | ||||
| import sys | ||||
| import pkg_resources | ||||
| import requests | ||||
| import json | ||||
| from collections import deque | ||||
|  | ||||
| required_packages = { | ||||
|     'grist-api': 'latest', | ||||
|     'colorama': 'latest', | ||||
|     'requests': '2.31.0', | ||||
|     'urllib3': '2.0.7', | ||||
|     'charset-normalizer': '3.3.2' | ||||
| } | ||||
|  | ||||
| installed_packages = {pkg.key: pkg.version for pkg in pkg_resources.working_set} | ||||
|  | ||||
| for package, version in required_packages.items(): | ||||
|     if package not in installed_packages or (version != 'latest' and installed_packages[package] != version): | ||||
|         if version == 'latest': | ||||
|             subprocess.check_call([sys.executable, '-m', 'pip', 'install', package, '--break-system-packages']) | ||||
|         else: | ||||
|             subprocess.check_call([sys.executable, '-m', 'pip', 'install', f"{package}=={version}", '--break-system-packages']) | ||||
|  | ||||
| from grist_api import GristDocAPI | ||||
| import colorama | ||||
|  | ||||
| import logging | ||||
| import socket | ||||
|  | ||||
| def self_update(logger): | ||||
|     logger.info("Checking for updates..") | ||||
|     script_path = os.path.abspath(__file__) | ||||
|     update_url = "https://gitea.vvzvlad.xyz/vvzvlad/ritual/raw/branch/main-22aug/checker.py" | ||||
|     try: | ||||
|         response = requests.get(update_url, timeout=10) | ||||
|         if response.status_code == 200: | ||||
|             current_content = "" | ||||
|             with open(script_path, 'r', encoding='utf-8') as f: | ||||
|                 current_content = f.read() | ||||
|              | ||||
|             if current_content != response.text: | ||||
|                 with open(script_path, 'w', encoding='utf-8') as f: | ||||
|                     f.write(response.text) | ||||
|                 logger.info("Script updated successfully, restarting") | ||||
|                 os.execv(sys.executable, ['python3'] + sys.argv) | ||||
|             else: | ||||
|                 logger.info("Script is up to date") | ||||
|         else: | ||||
|             logger.error(f"Failed to download update, status code: {response.status_code}") | ||||
|     except Exception as e: | ||||
|         logger.error(f"Update error: {str(e)}") | ||||
|  | ||||
| class GRIST: | ||||
|     def __init__(self, server, doc_id, api_key, logger): | ||||
|         self.server = server | ||||
|         self.doc_id = doc_id | ||||
|         self.api_key = api_key | ||||
|         self.logger = logger | ||||
|         self.grist = GristDocAPI(doc_id, server=server, api_key=api_key) | ||||
|  | ||||
|     def table_name_convert(self, table_name): | ||||
|         return table_name.replace(" ", "_") | ||||
|  | ||||
|     def to_timestamp(self, dtime: datetime) -> int: | ||||
|         if dtime.tzinfo is None: | ||||
|             dtime = dtime.replace(tzinfo=timezone(timedelta(hours=3)))  | ||||
|         return int(dtime.timestamp()) | ||||
|  | ||||
|     def insert_row(self, data, table): | ||||
|         data = {key.replace(" ", "_"): value for key, value in data.items()} | ||||
|         row_id = self.grist.add_records(self.table_name_convert(table), [data]) | ||||
|         return row_id | ||||
|  | ||||
|     def update_column(self, row_id, column_name, value, table): | ||||
|         if isinstance(value, datetime): | ||||
|             value = self.to_timestamp(value) | ||||
|         column_name = column_name.replace(" ", "_") | ||||
|         self.grist.update_records(self.table_name_convert(table), [{ "id": row_id, column_name: value }]) | ||||
|  | ||||
|     def delete_row(self, row_id, table): | ||||
|         self.grist.delete_records(self.table_name_convert(table), [row_id]) | ||||
|  | ||||
|     def update(self, row_id, updates, table): | ||||
|         for column_name, value in updates.items(): | ||||
|             if isinstance(value, datetime): | ||||
|                 updates[column_name] = self.to_timestamp(value) | ||||
|         updates = {column_name.replace(" ", "_"): value for column_name, value in updates.items()} | ||||
|         self.grist.update_records(self.table_name_convert(table), [{"id": row_id, **updates}]) | ||||
|  | ||||
|     def fetch_table(self, table): | ||||
|         return self.grist.fetch_table(self.table_name_convert(table)) | ||||
|  | ||||
|     def find_record(self, id=None, state=None, name=None, table=None): | ||||
|         if table is None: | ||||
|             raise ValueError("Table is not specified") | ||||
|         table_data = self.grist.fetch_table(self.table_name_convert(table)) | ||||
|         if id is not None: | ||||
|             record = [row for row in table_data if row.id == id] | ||||
|             return record | ||||
|         if state is not None and name is not None: | ||||
|             record = [row for row in table_data if row.State == state and row.name == name] | ||||
|             return record | ||||
|         if state is not None: | ||||
|             record = [row for row in table_data if row.State == state] | ||||
|             return record | ||||
|         if name is not None: | ||||
|             record = [row for row in table_data if row.Name == name] | ||||
|             return record | ||||
|  | ||||
|     def find_settings(self, key, table): | ||||
|         table = self.fetch_table(self.table_name_convert(table)) | ||||
|         for record in table: | ||||
|             if record.Setting == key: | ||||
|                 if record.Value is None or record.Value == "": | ||||
|                     raise ValueError(f"Setting {key} blank") | ||||
|                 return record.Value | ||||
|         raise ValueError(f"Setting {key} not found") | ||||
|  | ||||
| def clean_ansi(text): | ||||
|     ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') | ||||
|     return ansi_escape.sub('', text) | ||||
|  | ||||
| def format_number(number_str): | ||||
|     try: | ||||
|         number = int(number_str) | ||||
|         if number >= 1000: | ||||
|             value_in_k = number / 1000.0 | ||||
|             # Format to 3 decimal places if needed, remove trailing zeros and potentially the dot | ||||
|             formatted_num = f"{value_in_k:.3f}".rstrip('0').rstrip('.') | ||||
|             return f"{formatted_num}k" | ||||
|         return str(number) | ||||
|     except (ValueError, TypeError): | ||||
|         return "NaN" # Or some other indicator of invalid input | ||||
|  | ||||
| def check_logs(logger, initial_sync_count, previous_status): | ||||
|     """ | ||||
|     Checks docker logs for node status (Syncing, OK, Idle) and updates sync count. | ||||
|  | ||||
|     Args: | ||||
|         logger: The logger instance. | ||||
|         initial_sync_count: The sync count read from Grist at the start. | ||||
|         previous_status: The last known status read from Grist ('Sync', 'OK', 'Idle', or others). | ||||
|  | ||||
|     Returns: | ||||
|         A dictionary containing: | ||||
|         - status_message: A string describing the current status (e.g., "Sync: 123k (5)"). | ||||
|         - current_status_type: The type of the current status ('Sync', 'OK', 'Idle', 'Error'). | ||||
|         - current_sync_count: The updated sync count. | ||||
|     """ | ||||
|     current_sync_count = initial_sync_count # Initialize with the value from Grist | ||||
|  | ||||
|     try: | ||||
|         logs = subprocess.run(['docker', 'logs', '--since', '10m', 'infernet-node'], capture_output=True, text=True, check=True) | ||||
|         log_content = clean_ansi(logs.stdout) | ||||
|  | ||||
|         last_checking_info = None | ||||
|         last_ignored_id = None | ||||
|         last_head_sub_id = None | ||||
|  | ||||
|         # Regex patterns | ||||
|         checking_pattern = re.compile(r'Checking subscriptions.*last_sub_id=(\d+).*head_sub_id=(\d+).*num_subs_to_sync=(\d+)') | ||||
|         ignored_pattern = re.compile(r'Ignored subscription creation.*id=(\d+)') | ||||
|         head_sub_pattern = re.compile(r'head sub id is:\s*(\d+)') | ||||
|  | ||||
|         # Use deque to efficiently get the last few relevant lines if needed, | ||||
|         # but processing all lines and keeping the last match is simpler here. | ||||
|         for line in log_content.splitlines(): | ||||
|             match = checking_pattern.search(line) | ||||
|             if match: | ||||
|                 last_checking_info = { | ||||
|                     "last_sub_id": match.group(1), | ||||
|                     "head_sub_id": match.group(2), | ||||
|                     "num_subs_to_sync": int(match.group(3)) | ||||
|                 } | ||||
|                 continue # Prioritize checking_info | ||||
|  | ||||
|             match = ignored_pattern.search(line) | ||||
|             if match: | ||||
|                 last_ignored_id = match.group(1) | ||||
|                 continue | ||||
|  | ||||
|             match = head_sub_pattern.search(line) | ||||
|             if match: | ||||
|                 last_head_sub_id = match.group(1) | ||||
|                 # No continue here, allows checking_info from same timeframe to override | ||||
|  | ||||
|         current_status_type = "Idle" | ||||
|         status_message = "Idle" | ||||
|          | ||||
|         if last_checking_info: | ||||
|             formatted_id = format_number(last_checking_info["last_sub_id"]) | ||||
|             if last_checking_info["num_subs_to_sync"] > 0: | ||||
|                 current_status_type = "Sync" | ||||
|                 status_message = f"Sync: {formatted_id}" # Use current_sync_count | ||||
|                 logger.info(f"Node is syncing. Last sub ID: {last_checking_info['last_sub_id']}, Num subs to sync: {last_checking_info['num_subs_to_sync']}") | ||||
|             else: | ||||
|                 current_status_type = "OK" | ||||
|                 # Increment count only on transition from Sync to OK | ||||
|                 if previous_status == "Sync": | ||||
|                     current_sync_count += 1 # Increment local count | ||||
|                     logger.info(f"Sync completed. Sync count incremented to {current_sync_count}.") | ||||
|                 status_message = f"OK: {formatted_id}" # Use current_sync_count | ||||
|                 logger.info(f"Node is OK. Last sub ID: {last_checking_info['last_sub_id']}") | ||||
|          | ||||
|         elif last_ignored_id: | ||||
|             # Fallback to "Ignored" logs if "Checking" is missing | ||||
|             formatted_id = format_number(last_ignored_id) | ||||
|             current_status_type = "Sync" # Assume sync if we only see ignored creations recently | ||||
|             status_message = f"Sync: {formatted_id}" # Use current_sync_count | ||||
|             logger.info(f"Node possibly syncing (based on ignored logs). Last ignored ID: {last_ignored_id}") | ||||
|  | ||||
|         elif last_head_sub_id: | ||||
|             # Fallback to "head sub id" if others are missing | ||||
|             formatted_id = format_number(last_head_sub_id) | ||||
|             current_status_type = "OK" # Assume OK if this is the latest relevant info | ||||
|             # Don't increment sync count here, only on Sync -> OK transition based on "Checking" logs | ||||
|             status_message = f"OK: {formatted_id}" # Use current_sync_count | ||||
|             logger.info(f"Node status based on head sub id. Head sub ID: {last_head_sub_id}") | ||||
|              | ||||
|         else: | ||||
|             logger.info("No relevant subscription log entries found in the last 10 minutes. Status: Idle.") | ||||
|             status_message = "Idle" | ||||
|             current_status_type = "Idle" | ||||
|  | ||||
|         # Return the results instead of writing to a file | ||||
|         return { | ||||
|             "status_message": status_message, | ||||
|             "current_status_type": current_status_type, | ||||
|             "current_sync_count": current_sync_count | ||||
|         } | ||||
|  | ||||
|     except subprocess.CalledProcessError as e: | ||||
|         error_msg = f"Error: Docker logs failed ({e.returncode})" | ||||
|         logger.error(f"Error running docker logs command: {e.stderr or e.stdout or e}") | ||||
|         # Return error status and original sync count | ||||
|         return { | ||||
|             "status_message": error_msg, | ||||
|             "current_status_type": "Error", | ||||
|             "current_sync_count": initial_sync_count # Return original count on error | ||||
|         } | ||||
|     except Exception as e: | ||||
|         error_msg = "Error: Log processing failed" | ||||
|         logger.error(f"Unexpected error processing logs: {e}", exc_info=True) | ||||
|         # Return error status and original sync count | ||||
|         return { | ||||
|             "status_message": error_msg, | ||||
|             "current_status_type": "Error", | ||||
|             "current_sync_count": initial_sync_count # Return original count on error | ||||
|         } | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     colorama.init(autoreset=True) | ||||
|     logger = logging.getLogger("Checker") | ||||
|     logger.setLevel(logging.INFO) | ||||
|     formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") | ||||
|     ch = logging.StreamHandler() | ||||
|     ch.setFormatter(formatter) | ||||
|     logger.addHandler(ch) | ||||
|  | ||||
|     logger.info("Checker started") | ||||
|     self_update(logger) | ||||
|     #random_sleep = random.randint(1, 60) | ||||
|     #logger.info(f"Sleeping for {random_sleep} seconds") | ||||
|     #time.sleep(random_sleep) | ||||
|  | ||||
|     grist_data = {} | ||||
|     with open('/root/node/grist.json', 'r', encoding='utf-8') as f: | ||||
|         grist_data = json.loads(f.read()) | ||||
|  | ||||
|     GRIST_ROW_NAME = socket.gethostname() | ||||
|     NODES_TABLE = "Nodes" | ||||
|     grist = GRIST(grist_data.get('grist_server'), grist_data.get('grist_doc_id'), grist_data.get('grist_api_key'), logger) | ||||
|     current_vm = grist.find_record(name=GRIST_ROW_NAME, table=NODES_TABLE)[0] | ||||
|     def grist_callback(msg): grist.update(current_vm.id, msg, NODES_TABLE) | ||||
|  | ||||
|     # Initialize updates dictionary | ||||
|     initial_updates = {} | ||||
|     # Check and prepare update for Syncs if it's None or empty | ||||
|     if not current_vm.Syncs: # Handles None, empty string, potentially 0 if that's how Grist stores it | ||||
|         initial_updates["Syncs"] = 0 | ||||
|     # Check and prepare update for Reboots if it's None or empty | ||||
|     if not current_vm.Reboots: # Handles None, empty string, potentially 0 | ||||
|         initial_updates["Reboots"] = 0 | ||||
|  | ||||
|     # If there are updates, send them to Grist | ||||
|     if initial_updates: | ||||
|         try: | ||||
|             logger.info(f"Found empty initial values, updating Grist: {initial_updates}") | ||||
|             grist.update(current_vm.id, initial_updates, NODES_TABLE) | ||||
|             # Re-fetch the record to ensure subsequent logic uses the updated values | ||||
|             current_vm = grist.find_record(name=GRIST_ROW_NAME, table=NODES_TABLE)[0] | ||||
|             logger.info("Grist updated successfully with initial zeros.") | ||||
|         except Exception as e: | ||||
|             logger.error(f"Failed to update Grist with initial zeros: {e}") | ||||
|             # Decide how to proceed: maybe exit, maybe continue with potentially incorrect defaults | ||||
|             # For now, we'll log the error and continue using the potentially incorrect defaults from the first fetch | ||||
|  | ||||
|     # Get initial state from Grist (now potentially updated) | ||||
|     initial_sync_count = int(current_vm.Syncs or 0) # 'or 0' still useful as fallback | ||||
|     reboot_count = int(current_vm.Reboots or 0) # 'or 0' still useful as fallback | ||||
|     # Determine previous status type based on Health string (simplified) | ||||
|     previous_health_status = current_vm.Health or "Idle" | ||||
|     previous_status_type = "Idle" # Default | ||||
|     if previous_health_status.startswith("Sync"): | ||||
|         previous_status_type = "Sync" | ||||
|     elif previous_health_status.startswith("OK"): | ||||
|         previous_status_type = "OK" | ||||
|     elif previous_health_status.startswith("Error"): | ||||
|         previous_status_type = "Error" # Consider error state | ||||
|  | ||||
|     logger.info(f"Initial state from Grist - Syncs: {initial_sync_count}, Health: {previous_health_status}, Reboots: {reboot_count}") | ||||
|  | ||||
|     for attempt in range(3): | ||||
|         try: | ||||
|             vm_ip = os.popen("ip -4 addr show eth0 | grep -oP '(?<=inet )[^/]+'").read() | ||||
|             vm_ip = vm_ip.strip() | ||||
|             if vm_ip == "": | ||||
|                 logger.error("Failed to get VM IP address") | ||||
|             else: | ||||
|                 logger.info(f"VM IP address: {vm_ip}") | ||||
|                 grist_callback({"IP": f"{vm_ip}"}) | ||||
|  | ||||
|  | ||||
|             # Pass initial state to check_logs | ||||
|             result = check_logs(logger, initial_sync_count, previous_status_type) | ||||
|  | ||||
|             grist_updates = {"Health": result["status_message"]} | ||||
|              | ||||
|             # Update Syncs count in Grist only if it changed | ||||
|             if result["current_sync_count"] != initial_sync_count: | ||||
|                 grist_updates["Syncs"] = result["current_sync_count"] | ||||
|                 logger.info(f"Sync count changed from {initial_sync_count} to {result['current_sync_count']}") | ||||
|  | ||||
|             # Send updates to Grist | ||||
|             grist_callback(grist_updates) | ||||
|             logger.info(f"Status update sent: {grist_updates}") | ||||
|              | ||||
|             # Reboot logic (remains mostly the same, reads Reboots from current_vm) | ||||
|             if result["current_status_type"] == "Idle": # Check type, not message | ||||
|                 uptime_seconds = os.popen("cat /proc/uptime | cut -d'.' -f1").read() | ||||
|                 uptime_seconds = int(uptime_seconds) | ||||
|                 if uptime_seconds > 60*60*4: | ||||
|                     reboot_count = int(current_vm.Reboots or 0) | ||||
|                     reboot_count += 1 | ||||
|                     # Include reboot count in the final Grist update before rebooting | ||||
|                     grist_updates = { "Health": "Rebooting", "Reboots": reboot_count } | ||||
|                     grist_callback(grist_updates) | ||||
|                     logger.info(f"Idle detected for >4 hours (uptime: {uptime_seconds}s). Rebooting. Reboot count: {reboot_count}") | ||||
|                     os.system("reboot") | ||||
|             break # Exit loop on success | ||||
|         except Exception as e: | ||||
|             logger.error(f"Error in main loop, attempt {attempt+1}/3: {e}", exc_info=True) | ||||
|             if attempt == 2: | ||||
|                 # Log final error to Grist on last attempt | ||||
|                 try: | ||||
|                     grist_updates = { "Health": f"Error: Main loop failed - {e}" } | ||||
|                     grist_callback(grist_updates) | ||||
|                 except Exception as grist_e: | ||||
|                     logger.error(f"Failed to log final error to Grist: {grist_e}") | ||||
|             time.sleep(5) # Wait before retrying | ||||
| @ -1,8 +1,6 @@ | ||||
| version: '3' | ||||
|  | ||||
| services: | ||||
|   node: | ||||
|     image: ritualnetwork/infernet-node:1.0.0 | ||||
|     image: ritualnetwork/infernet-node:1.4.0 | ||||
|     ports: | ||||
|       - "0.0.0.0:4000:4000" | ||||
|     volumes: | ||||
| @ -16,11 +14,16 @@ services: | ||||
|       - redis | ||||
|       - infernet-anvil | ||||
|     restart: | ||||
|       on-failure | ||||
|       unless-stopped | ||||
|     extra_hosts: | ||||
|       - "host.docker.internal:host-gateway" | ||||
|     stop_grace_period: 1m | ||||
|     container_name: infernet-node | ||||
|     logging: | ||||
|       driver: "json-file" | ||||
|       options: | ||||
|         max-file: 5 | ||||
|         max-size: 10m | ||||
|  | ||||
|   redis: | ||||
|     image: redis:latest | ||||
| @ -32,7 +35,12 @@ services: | ||||
|       - ./redis.conf:/usr/local/etc/redis/redis.conf | ||||
|       - redis-data:/data | ||||
|     restart: | ||||
|       on-failure | ||||
|       unless-stopped | ||||
|     logging: | ||||
|       driver: "json-file" | ||||
|       options: | ||||
|         max-file: 5 | ||||
|         max-size: 10m | ||||
|  | ||||
|   fluentbit: | ||||
|     image: fluent/fluent-bit:latest | ||||
| @ -46,16 +54,28 @@ services: | ||||
|     networks: | ||||
|       - network | ||||
|     restart: | ||||
|       on-failure | ||||
|       unless-stopped | ||||
|     logging: | ||||
|       driver: "json-file" | ||||
|       options: | ||||
|         max-file: 5 | ||||
|         max-size: 10m | ||||
|  | ||||
|   infernet-anvil: | ||||
|     image: ritualnetwork/infernet-anvil:1.0.0 | ||||
|     command: --host 0.0.0.0 --port 3000 --load-state infernet_deployed.json -b 1 | ||||
|     command: --host 0.0.0.0 --port 3000 --load-state infernet_deployed.json --prune-history -b 1 | ||||
|     ports: | ||||
|       - "8545:3000" | ||||
|     networks: | ||||
|       - network | ||||
|     container_name: infernet-anvil | ||||
|     restart: | ||||
|       unless-stopped | ||||
|     logging: | ||||
|       driver: "json-file" | ||||
|       options: | ||||
|         max-file: 5 | ||||
|         max-size: 10m | ||||
|  | ||||
| networks: | ||||
|   network: | ||||
|  | ||||
							
								
								
									
										5
									
								
								grist.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								grist.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| { | ||||
|   "grist_server": "###GRIST_SERVER###", | ||||
|   "grist_doc_id": "###GRIST_DOC_ID###", | ||||
|   "grist_api_key": "###GRIST_API_KEY###" | ||||
| } | ||||
							
								
								
									
										268
									
								
								playbook.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								playbook.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,268 @@ | ||||
| --- | ||||
| - name: System Setup and Configuration | ||||
|   hosts: all | ||||
|   become: true | ||||
|  | ||||
|   tasks: | ||||
|     - name: Set locale to C.UTF-8 | ||||
|       command: localectl set-locale LANG=C.UTF-8 | ||||
|  | ||||
|     - name: Create APT configuration file to assume yes | ||||
|       ansible.builtin.copy: | ||||
|         dest: /etc/apt/apt.conf.d/90forceyes | ||||
|         content: | | ||||
|           APT::Get::Assume-Yes "true"; | ||||
|         mode: '0644' | ||||
|  | ||||
|     - name: Append command to .bash_history | ||||
|       ansible.builtin.blockinfile: | ||||
|         path: "~/.bash_history" | ||||
|         create: true | ||||
|         block: | | ||||
|           cd ~/node; bash rebuild.sh | ||||
|           nano ~/node/projects/hello-world/container/config.json | ||||
|           docker logs infernet-node -f | ||||
|           docker logs --since 10m infernet-node -f | ||||
|           journalctl -u node-checker.service | ||||
|           journalctl -u grpcbalancer.service | ||||
|           nano ~/node/deploy/config.json | ||||
|           docker compose -f deploy/docker-compose.yaml down; docker compose -f deploy/docker-compose.yaml up -d | ||||
|         marker: "" | ||||
|         mode: '0644' | ||||
|  | ||||
|  | ||||
|     - name: Append command to .bash_rc | ||||
|       ansible.builtin.blockinfile: | ||||
|         path: "~/.bashrc" | ||||
|         create: true | ||||
|         insertafter: EOF | ||||
|         block: | | ||||
|           cd /root/node | ||||
|         marker: "" | ||||
|         mode: '0644' | ||||
|  | ||||
|     - name: Update /etc/bash.bashrc | ||||
|       ansible.builtin.blockinfile: | ||||
|         path: /etc/bash.bashrc | ||||
|         block: | | ||||
|           export HISTTIMEFORMAT='%F, %T ' | ||||
|           export HISTSIZE=10000 | ||||
|           export HISTFILESIZE=10000 | ||||
|           shopt -s histappend | ||||
|           export PROMPT_COMMAND='history -a' | ||||
|           export HISTCONTROL=ignoredups | ||||
|           export LANG=C.UTF-8 | ||||
|           export LC_ALL=C.UTF-8 | ||||
|           alias ls='ls --color=auto' | ||||
|           shopt -s cmdhist | ||||
|         create: true | ||||
|         marker: "" | ||||
|         mode: '0644' | ||||
|  | ||||
|     - name: Update .inputrc for the current user | ||||
|       ansible.builtin.blockinfile: | ||||
|         path: "{{ ansible_env.HOME }}/.inputrc" | ||||
|         block: | | ||||
|           "\e[A": history-search-backward | ||||
|           "\e[B": history-search-forward | ||||
|         create: true | ||||
|         marker: "" | ||||
|         mode: '0644' | ||||
|  | ||||
|     - name: Update ~/.nanorc | ||||
|       ansible.builtin.blockinfile: | ||||
|         path: "{{ ansible_env.HOME }}/.nanorc" | ||||
|         block: | | ||||
|           set nohelp | ||||
|           set tabsize 4 | ||||
|           set tabstospaces | ||||
|           set autoindent | ||||
|           set positionlog | ||||
|           set backup | ||||
|           set backupdir /tmp/ | ||||
|           set locking | ||||
|           include /usr/share/nano/*.nanorc | ||||
|         create: true | ||||
|         marker: "" | ||||
|         mode: '0644' | ||||
|  | ||||
|     - name: Set hostname | ||||
|       ansible.builtin.hostname: | ||||
|         name: "{{ serverid }}" | ||||
|  | ||||
|     - name: Ensure hostname is in /etc/hosts | ||||
|       ansible.builtin.lineinfile: | ||||
|         path: /etc/hosts | ||||
|         regexp: '^127\.0\.1\.1\s+' | ||||
|         line: "127.0.1.1 {{ serverid }}" | ||||
|         state: present | ||||
|  | ||||
|     #- name: Update and upgrade apt | ||||
|     #  ansible.builtin.apt: | ||||
|     #    update_cache: true | ||||
|     #    upgrade: dist | ||||
|     #    force_apt_get: true | ||||
|     #  register: apt_update_result | ||||
|     #  until: apt_update_result is success | ||||
|  | ||||
|     - name: Install necessary packages | ||||
|       ansible.builtin.apt: | ||||
|         name: | ||||
|           - apt-transport-https | ||||
|           - ca-certificates | ||||
|           - curl | ||||
|           - software-properties-common | ||||
|           - make | ||||
|           - iftop | ||||
|           - python3 | ||||
|         state: present | ||||
|  | ||||
|     - name: Install pip package web3 | ||||
|       ansible.builtin.pip: | ||||
|         name: web3 | ||||
|         extra_args: --break-system-packages | ||||
|  | ||||
| #    - name: Install Docker | ||||
| #      ansible.builtin.shell: curl -sL https://get.docker.com | sudo sh - | ||||
| # | ||||
|     - name: Update Docker daemon configuration for journald logging | ||||
|       ansible.builtin.copy: | ||||
|         dest: /etc/docker/daemon.json | ||||
|         content: | | ||||
|           {  | ||||
|           "log-driver": "journald", | ||||
|           "registry-mirrors": ["https://dockerregistry.vvzvlad.xyz"] | ||||
|           } | ||||
|  | ||||
|     - name: Restart Docker | ||||
|       ansible.builtin.service: | ||||
|         name: docker | ||||
|         state: restarted | ||||
|  | ||||
|     - name: Docker pull hello-world | ||||
|       ansible.builtin.shell: docker pull ritualnetwork/hello-world-infernet:latest | ||||
|  | ||||
| #    - name: Update journald log SystemMaxUse=2G configuration | ||||
| #      ansible.builtin.lineinfile: | ||||
| #        path: /etc/systemd/journald.conf | ||||
| #        regexp: '^SystemMaxUse=' | ||||
| #        line: 'SystemMaxUse=2G' | ||||
| #        state: present | ||||
| #        backup: yes | ||||
| #        validate: 'journaldctl check-config %s' | ||||
| # | ||||
| #    - name: Restart journald | ||||
| #      ansible.builtin.service: | ||||
| #        name: systemd-journald | ||||
| #        state: restarted | ||||
|  | ||||
|     - name: Setup Foundry | ||||
|       ansible.builtin.shell: | | ||||
|         mkdir -p ~/foundry && cd ~/foundry | ||||
|         curl -L https://foundry.paradigm.xyz | bash | ||||
|       args: | ||||
|         executable: /bin/bash | ||||
|  | ||||
|     - name: Run foundryup | ||||
|       ansible.builtin.shell: | | ||||
|         source ~/.bashrc && foundryup | ||||
|       args: | ||||
|         executable: /bin/bash | ||||
|  | ||||
|     - name: Clone repository | ||||
|       ansible.builtin.git: | ||||
|         repo: https://gitea.vvzvlad.xyz/vvzvlad/ritual.git | ||||
|         dest: "{{ ansible_env.HOME }}/node" | ||||
|         version: "{{ git_version }}" | ||||
|         force: true | ||||
|       async: "{{ 60 * 15 }}" | ||||
|       poll: 30 | ||||
|  | ||||
|     - name: Update environment variables | ||||
|       ansible.builtin.shell: | | ||||
|         chmod +x ./update.sh | ||||
|         ./update.sh ID "{{ serverid }}"  | ||||
|         ./update.sh GRIST_SERVER "{{ grist_server }}" | ||||
|         ./update.sh GRIST_DOC_ID "{{ grist_doc_id }}" | ||||
|         ./update.sh GRIST_API_KEY "{{ grist_api_key }}" | ||||
|         ./update.sh WALLET_ADDRESS "{{ wallet }}" | ||||
|         ./update.sh PRIVATE_KEY "{{ private_key }}" | ||||
|         ./update.sh RPC_URL "{{ rpc_url }}" | ||||
|       args: | ||||
|         chdir: "{{ ansible_env.HOME }}/node" | ||||
|       changed_when: false | ||||
|  | ||||
|  | ||||
|     - name: Install Forge and Infernet SDK | ||||
|       ansible.builtin.shell: | | ||||
|         rm -rf {{ ansible_env.HOME }}/node/projects/hello-world/contracts/lib/forge-std | ||||
|         rm -rf {{ ansible_env.HOME }}/node/projects/hello-world/contracts/lib/infernet-sdk | ||||
|         cd {{ ansible_env.HOME }}/foundry && source {{ ansible_env.HOME }}/.bashrc && foundryup | ||||
|         cd {{ ansible_env.HOME }}/node/projects/hello-world/contracts | ||||
|         forge install foundry-rs/forge-std | ||||
|         forge install ritual-net/infernet-sdk | ||||
|       args: | ||||
|         executable: /bin/bash | ||||
|  | ||||
|     - name: Deploy container | ||||
|       ansible.builtin.shell: project=hello-world make deploy-container | ||||
|       args: | ||||
|         chdir: "{{ ansible_env.HOME }}/node" | ||||
|  | ||||
|     - name: Deploy contracts | ||||
|       ansible.builtin.shell: project=hello-world make deploy-contracts 2>&1 | ||||
|       register: contract_deploy_output | ||||
|       args: | ||||
|         chdir: "{{ ansible_env.HOME }}/node" | ||||
|         executable: /bin/bash | ||||
|       retries: 5 | ||||
|       delay: 120 | ||||
|       async: 120 | ||||
|       poll: 30 | ||||
|       until: '"ONCHAIN EXECUTION COMPLETE & SUCCESSFUL" in contract_deploy_output.stdout' | ||||
|       failed_when: false | ||||
|  | ||||
|     - name: Update CallContract.s.sol with contract address | ||||
|       ansible.builtin.shell: bash update_contracts.sh | ||||
|       args: | ||||
|         chdir: "{{ ansible_env.HOME }}/node" | ||||
|  | ||||
|     - name: Call contract | ||||
|       ansible.builtin.shell: project=hello-world make call-contract 2>&1 | ||||
|       register: contract_call_output | ||||
|       args: | ||||
|         chdir: "{{ ansible_env.HOME }}/node" | ||||
|         executable: /bin/bash | ||||
|       retries: 5 | ||||
|       delay: 120 | ||||
|       async: 120 | ||||
|       poll: 30 | ||||
|       until: '"ONCHAIN EXECUTION COMPLETE & SUCCESSFUL" in contract_call_output.stdout' | ||||
|       failed_when: false | ||||
|  | ||||
|     - name: Copy checker service file | ||||
|       ansible.builtin.copy: | ||||
|         dest: /etc/systemd/system/node-checker.service | ||||
|         content: | | ||||
|           [Unit] | ||||
|           Description=Node Checker Service | ||||
|           After=network.target | ||||
|  | ||||
|           [Service] | ||||
|           Type=simple | ||||
|           User=root | ||||
|           WorkingDirectory={{ ansible_env.HOME }}/node | ||||
|           ExecStart=/usr/bin/python3 {{ ansible_env.HOME }}/node/checker.py | ||||
|           Restart=always | ||||
|           RestartSec=600 | ||||
|  | ||||
|           [Install] | ||||
|           WantedBy=multi-user.target | ||||
|         mode: '0644' | ||||
|  | ||||
|     - name: Enable and start node-checker service | ||||
|       ansible.builtin.systemd: | ||||
|         name: node-checker | ||||
|         enabled: yes | ||||
|         state: started | ||||
|         daemon_reload: yes | ||||
| @ -11,6 +11,7 @@ update-tag: | ||||
|  | ||||
| run: build | ||||
| 	docker run \ | ||||
| 		--restart unless-stopped \ | ||||
| 		-p 3000:3000 $(TAG) | ||||
|  | ||||
| # You may need to set up a docker builder, to do so run: | ||||
|  | ||||
| @ -5,28 +5,27 @@ | ||||
|     }, | ||||
|     "chain": { | ||||
|         "enabled": true, | ||||
|         "trail_head_blocks": 0, | ||||
|         "rpc_url": "http://host.docker.internal:8545", | ||||
|         "registry_address": "0x663F3ad617193148711d28f5334eE4Ed07016602", | ||||
|         "trail_head_blocks": 3, | ||||
|         "rpc_url": "###RPC_URL###", | ||||
|         "registry_address": "0x3B1554f346DFe5c482Bb4BA31b880c1C18412170", | ||||
|         "wallet": { | ||||
|             "max_gas_limit": 4000000, | ||||
|             "private_key": "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" | ||||
|             "private_key": "###PRIVATE_KEY###" | ||||
|         }, | ||||
|         "snapshot_sync": { | ||||
|             "sleep": 3, | ||||
|             "batch_size": 800, | ||||
|             "starting_sub_id": 242029, | ||||
|             "sync_period": 30 | ||||
|         } | ||||
|     }, | ||||
|     "startup_wait": 1.0, | ||||
|     "docker": { | ||||
|         "username": "your-username", | ||||
|         "password": "" | ||||
|     }, | ||||
|     "redis": { | ||||
|         "host": "redis", | ||||
|         "port": 6379 | ||||
|     }, | ||||
|     "forward_stats": true, | ||||
|     "snapshot_sync": { | ||||
|         "sleep": 3, | ||||
|         "batch_size": 100 | ||||
|     }, | ||||
|  | ||||
|     "containers": [ | ||||
|         { | ||||
|             "id": "hello-world", | ||||
| @ -34,7 +33,7 @@ | ||||
|             "external": true, | ||||
|             "port": "3000", | ||||
|             "allowed_delegate_addresses": [], | ||||
|             "allowed_addresses": [], | ||||
|             "allowed_addresses": ["###WALLET_ADDRESS###"], | ||||
|             "allowed_ips": [], | ||||
|             "command": "--bind=0.0.0.0:3000 --workers=2", | ||||
|             "env": {}, | ||||
|  | ||||
| @ -2,8 +2,8 @@ | ||||
| .phony: deploy | ||||
|  | ||||
| # anvil's third default address | ||||
| sender := 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a | ||||
| RPC_URL := http://localhost:8545 | ||||
| sender := ###PRIVATE_KEY### | ||||
| RPC_URL :=  ###RPC_URL### | ||||
|  | ||||
| # deploying the contract | ||||
| deploy: | ||||
|  | ||||
| @ -14,7 +14,7 @@ contract Deploy is Script { | ||||
|         address deployerAddress = vm.addr(deployerPrivateKey); | ||||
|         console2.log("Loaded deployer: ", deployerAddress); | ||||
|  | ||||
|         address registry = 0x663F3ad617193148711d28f5334eE4Ed07016602; | ||||
|         address registry = 0x3B1554f346DFe5c482Bb4BA31b880c1C18412170; | ||||
|         // Create consumer | ||||
|         SaysGM saysGm = new SaysGM(registry); | ||||
|         console2.log("Deployed SaysHello: ", address(saysGm)); | ||||
|  | ||||
							
								
								
									
										8
									
								
								rebuild.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								rebuild.sh
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| set -e  | ||||
| cd ~/node | ||||
| project=hello-world make deploy-container | ||||
| project=hello-world make deploy-contracts | ||||
| bash update_contracts.sh | ||||
| project=hello-world make call-contract | ||||
							
								
								
									
										6
									
								
								toChecksumAddress.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								toChecksumAddress.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| import sys | ||||
| from web3 import Web3 | ||||
|  | ||||
| address = sys.argv[1] | ||||
| checksum_address = Web3.to_checksum_address(address) | ||||
| print(checksum_address) | ||||
							
								
								
									
										21
									
								
								update.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								update.sh
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| if [ "$#" -ne 2 ]; then | ||||
|     echo "Usage: $0 <PARAMETER> <NEW_VALUE>" | ||||
|     exit 1 | ||||
| fi | ||||
|  | ||||
| PARAMETER=$1 | ||||
| NEW_VALUE=$2 | ||||
|  | ||||
| # Список файлов | ||||
| FILES=( | ||||
|     "./projects/hello-world/container/config.json" | ||||
|     "./projects/hello-world/contracts/Makefile" | ||||
|     "grist.json" | ||||
| ) | ||||
|  | ||||
| for FILE in "${FILES[@]}"; do | ||||
|     EXPANDED_FILE=$(eval echo "$FILE") | ||||
|     sed -i "s|###$PARAMETER###|$NEW_VALUE|g" "$EXPANDED_FILE" | ||||
| done | ||||
							
								
								
									
										6
									
								
								update_contracts.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								update_contracts.sh
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| set -e  | ||||
| contract_address=$(jq -r '.transactions[0].contractAddress' projects/hello-world/contracts/broadcast/Deploy.s.sol/8453/run-latest.json) | ||||
| checksum_address=$(python3 toChecksumAddress.py $contract_address) | ||||
| sed -i "s/SaysGM(.*/SaysGM($checksum_address);/" projects/hello-world/contracts/script/CallContract.s.sol | ||||
							
								
								
									
										28
									
								
								ws.code-workspace
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								ws.code-workspace
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| { | ||||
| 	"folders": [ | ||||
| 		{ | ||||
| 			"path": "." | ||||
| 		}, | ||||
| 		{ | ||||
| 			"path": "../ritual-git" | ||||
| 		} | ||||
| 	], | ||||
| 	"settings": { | ||||
| 		"workbench.colorCustomizations": { | ||||
| 			"activityBar.activeBackground": "#fb94f8", | ||||
| 			"activityBar.background": "#fb94f8", | ||||
| 			"activityBar.foreground": "#15202b", | ||||
| 			"activityBar.inactiveForeground": "#15202b99", | ||||
| 			"activityBarBadge.background": "#777b05", | ||||
| 			"activityBarBadge.foreground": "#e7e7e7", | ||||
| 			"commandCenter.border": "#15202b99", | ||||
| 			"sash.hoverBorder": "#fb94f8", | ||||
| 			"titleBar.activeBackground": "#f963f5", | ||||
| 			"titleBar.activeForeground": "#15202b", | ||||
| 			"titleBar.inactiveBackground": "#f963f599", | ||||
| 			"titleBar.inactiveForeground": "#15202b99" | ||||
| 		}, | ||||
| 		"peacock.color": "#f963f5", | ||||
| 		"makefile.configureOnOpen": false | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	