package main import ( "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" "github.com/ethereum/go-ethereum/swarm/pss" "context" "bufio" "fmt" "crypto/ecdsa" "os" "bytes" "time" "io/ioutil" "encoding/json" "github.com/ethereum/go-ethereum/log" "strconv" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/swarm/storage/feed" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/swarm" // "github.com/ethereum/go-ethereum/swarm/network" bzzapi "github.com/ethereum/go-ethereum/swarm/api" // XXX: Shouldn't this be bzzclient? feedsapi "github.com/ethereum/go-ethereum/swarm/api/client" ) var ( // logger Log = log.New("hello-pss", "*") // XXX: Should be multiple, but cheating and only taking parent0 lastParent = "" ) // TODO: Ensure node starts in light node so it doesn't eat up a lot of disk space // XXX: Warning, this is bad design. Should use keystore for this. func getHexPrivateKey() string { privateKey, err := crypto.GenerateKey() if err != nil { Log.Crit("can't generate private key", err) } privateKeyBytes := crypto.FromECDSA(privateKey) // Debugging and basic key operations //publicKey := privateKey.Public() //publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) //if !ok { // log.Crit("error casting public key to ECDSA", err) //} //publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) //address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex() //fmt.Println("Private Key: ", hexutil.Encode(privateKeyBytes)) //fmt.Println("Public Key: ", hexutil.Encode(publicKeyBytes[4:])) //fmt.Println("Address: ", address) return hexutil.Encode(privateKeyBytes) } func getPrivateKeyFromFile(keyfile string) *ecdsa.PrivateKey { contents, err := ioutil.ReadFile(keyfile) if err != nil { log.Crit("Unable to read keyfile", keyfile) } println(string(contents)) privateKeyBytes, err := hexutil.Decode(string(contents)) if err != nil { log.Crit("Unable to get private key bytes", err) } privateKey, err := crypto.ToECDSA(privateKeyBytes) if err != nil { log.Crit("Unable to get private key", err) } return privateKey } // XXX: This shouldn't be needed func getp2pConfig(listenaddr string) p2p.Config { return p2p.Config{ ListenAddr: listenaddr, MaxPeers: 25, NAT: nat.Any(), } } // Create a node func newNode(port int) (*node.Node, error) { cfg := &node.DefaultConfig cfg.DataDir = fmt.Sprintf("%s%d", ".data_", port) // XXX: cfg.P2P.ListenAddr = fmt.Sprintf(":%d", port), should work if port == 9600 { cfg.P2P = getp2pConfig(":30400") } else if port == 9601 { cfg.P2P = getp2pConfig(":30401") } else if port == 9602 { cfg.P2P = getp2pConfig(":30402") } else { log.Crit("Ports be fucked up", "yeah") } cfg.HTTPPort = port cfg.IPCPath = "bzz.ipc" //fmt.Printf("Current data directory is %s\n", cfg.DataDir) return node.New(cfg) } func listenForMessages(msgC chan pss.APIMsg) { for { in := <-msgC // XXX: Who is in.key really? want readable public key here // XXX: The UX is an illusion // XXX: parsing logic should be same for pull from feed parsed := deserialize(string(in.Msg)) //fmt.Println("Alice old:", string(in.Msg)) // XXX Only one parent // TODO: Get all the parents here fmt.Println("Alice:", string(parsed.Text), "- parent0:", string(parsed.Parents[0])) //fmt.Println("\nReceived message", string(in.Msg), "from", fmt.Sprintf("%x", in.Key)) } } // TODO: Error handling if fail func postToFeed(client *rpc.Client, signer *feed.GenericSigner, receiver string, topic string, data []byte) { // For creating manifest, then posting, then finally getting // Create a new feed with user and topic. f := new(feed.Feed) f.User = signer.Address() f.Topic, _ = feed.NewTopic("bob", nil) query := feed.NewQueryLatest(f, lookup.NoClue) // XXX: Ok feeds seems fairly broken //httpClient := feedsapi.NewClient("https://swarm-gateways.net") // Cheating httpClient := feedsapi.NewClient("http://localhost:9602") // XXX 9600 // local sender alice //httpClient := feedsapi.NewClient("http://localhost:9600") //XXX doesnt even work //httpClient := feedsapi.NewClient("https://swarm-gateways.net") // XXX: Post to multiple feeds? //fmt.Println("signer Address: ", f.User.Hex()) request, err := httpClient.GetFeedRequest(query, "") if err != nil { fmt.Printf("Error retrieving feed status: %s", err.Error()) } request.SetData(data) if err = request.Sign(signer); err != nil { fmt.Printf("Error signing feed update: %s", err.Error()) } //fmt.Println("*** signed request", request) // manifest, err := httpClient.CreateFeedWithManifest(request) // if err != nil { // fmt.Printf("Error getting manifest: %s", manifest) // } // fmt.Println("MANIFEST:", manifest) // XXX: What do I want to do with feeds manifest? // 567f611190b2758fa625b3be14b2b9becf6f0e8887015b7c40d6cbe0e5fa14aa // Success: this works, also from 9601 Bob: // curl 'http://localhost:9600/bzz-feed:/?user=0xBCa21d9c6031b1965a9e0233D9B905d2f10CA259&name=bob' // XXX: Why do we need the second argument manifestAddressOrDomain? // It's already baked into httpClient and query. // Indeed: // > You only need to provide either manifestAddressOrDomain or Query to QueryFeed(). Set to "" or nil respectively. // response, err := httpClient.QueryFeed(query, "") // if err != nil { // fmt.Println("QueryFeed error", err) // } // buf := new(bytes.Buffer) // buf.ReadFrom(response) // feedStr := buf.String() // fmt.Println("Feed result: ", feedStr) // XXX Want to set level and time? // POST /bzz-feed:/?topic=&user=&level=&time=