{"id":18349258,"url":"https://github.com/pvarentsov/powtcp","last_synced_at":"2025-04-06T09:32:00.336Z","repository":{"id":205859936,"uuid":"708054950","full_name":"pvarentsov/powtcp","owner":"pvarentsov","description":"Proof of Work protected TCP server.","archived":false,"fork":false,"pushed_at":"2023-11-08T06:55:17.000Z","size":1459,"stargazers_count":30,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-21T21:22:56.927Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pvarentsov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-21T11:43:08.000Z","updated_at":"2025-02-23T11:55:00.000Z","dependencies_parsed_at":"2024-06-21T19:00:00.692Z","dependency_job_id":"a6ac81f4-1890-4c16-a809-d3190abd4dcf","html_url":"https://github.com/pvarentsov/powtcp","commit_stats":null,"previous_names":["pvarentsov/powtcp"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvarentsov%2Fpowtcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvarentsov%2Fpowtcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvarentsov%2Fpowtcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvarentsov%2Fpowtcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pvarentsov","download_url":"https://codeload.github.com/pvarentsov/powtcp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247463745,"owners_count":20942935,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T21:21:17.648Z","updated_at":"2025-04-06T09:31:59.934Z","avatar_url":"https://github.com/pvarentsov.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# powtcp\n\nThis project is a simple example of [Proof of work (PoW)](https://en.wikipedia.org/wiki/Proof_of_work) protected TCP server. It implements challenge-response protocol and uses [hashcash](https://en.wikipedia.org/wiki/Hashcash) algorithm.\n\n\u003cp align=\"center\"\u003e \n  \u003cimg src=\"assets/demo.png\"\u003e\n\u003c/p\u003e\n\n## Messaging\n\nThe server and client communicate using an internal messaging protocol. Each message ends with the `\\n` character. It's used to separeate messages from each other.\n\nA message consists of a command and a payload. They are separated by the `:` character. The payload can be any string without `\\n` character. It's not very convenient in real life, but in this project all payloads are fixed and don't contain `\\n` character.\n\nSupported commands:\n* `0` - *`Error`* (server -\u003e client);\n* `1` - *`RequestPuzzle`* (client -\u003e server);\n* `2` - *`ResponsePuzzle`* (server -\u003e client);\n* `3` - *`RequestResource`* (client -\u003e server);\n* `4` - *`ResponseResource`* (server -\u003e client).\n\nA messaging is implemented in the [`message`](./internal/pkg/lib/message/message.go) package.\n\n## PoW\n\n**PoW** is implemented with a challenge-response protocol:\n\n1. The client establishes a tcp connection with the server. The server starts to listening to client messages.\n2. The client sends the *`RequestPuzzle`* command to receive a puzzle from server. \n   \n   Message: `1:\\n`.\n3. The server generates a new puzzle using a hashcash algorithm, stores a puzzle in the cache with some TTL and sends the *`ResponsePuzzle`* command with this puzzle to the client. \n   \n   Message: `2:puzzle\\n`.\n4. The client receives a puzzle and tries to compute a puzzle hash with enough number of zero bits in the beggining. Than the client requests a resource sending a solved puzzle in the *`RequestResource`* command. \n   \n   Message: `3:solved-puzzle\\n`.\n5. The server receives the solved puzzle, checks TTL and sends *`ResponseResource`* command with some resource if that puzzle was solved correctly. \n   \n   Message: `4:some-resource\\n`.\n   \n**Implementation**:\n\n* [`hashcash algorithm`](./internal/pkg/lib/hashcash/hashcash.go);\n* [`server service`](./internal/pkg/service/service_server.go);\n* [`client service`](./internal/pkg/service/service_client.go).\n\n## How To\n\n### Requirements\n\n* [Go 1.21+](https://go.dev/doc/install);\n* [Docker](https://docs.docker.com/engine/install/) and [docker-compose](https://docs.docker.com/compose/install/).\n\n### Docker\n\n```bash\n# Run client and server just for demo\n$ docker-compose up\n\n# Run server listening on 8080 port\n$ docker-compose up -d server\n```\n\n### Makefile\n\n```bash\n$ make help\n\nUsage: make [command]\n\nCommands:\n\n build-server          Build server app\n build-client          Build client app\n\n run-server            Run server app\n run-client            Run client app\n\n test                  Run tests\n fmt                   Format code\n```\n\n### Go\n\n```bash\n# Build server\n$ go build -o ./bin/server ./cmd/server/*.go\n\n# Build client\n$ go build -o ./bin/client ./cmd/client/*.go\n\n# Run server\n$ ./bin/server\n\n# Run client\n$ ./bin/client\n```\n\n### Configuration\n\nServer and client applications support configuration from `.yaml` or `.env` files or from environment variables. Applications use [default configuration](./internal/pkg/lib/config/config.go) if a custom configuration not passed.\n\n**Server**\n\n```bash\n# Run server passing yaml config file\n$ ./bin/server --config config.yaml\n\n# Run server passing env config file\n$ ./bin/server --config config.env\n\n# Or run server using environment variables\n$ ./bin/server\n```\n\n**Client**\n\n```bash\n# Run client passing yaml config file\n$ ./bin/client --config config.yaml\n\n# Run client passing env config file\n$ ./bin/client --config config.env\n\n# Or run client using environment variables\n$ ./bin/client\n```\n\n**Templates** are available in the [config](./config/) folder.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpvarentsov%2Fpowtcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpvarentsov%2Fpowtcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpvarentsov%2Fpowtcp/lists"}