diff options
author | Joop Kiefte <ikojba@gmail.com> | 2021-12-12 02:44:11 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-12 02:44:11 +0000 |
commit | 407a75942f8bb7758f40bb04714d2ff0964972e1 (patch) | |
tree | 18f671d672e4eecd00ad650fe6701bc44ef9eeff | |
parent | 7f41a498b057d2ab180d288f212e0adc498e203d (diff) |
Implemented paging and improved POW calculation
-rw-r--r-- | main.go | 152 | ||||
-rw-r--r-- | message/message.go | 16 | ||||
-rw-r--r-- | message/message_test.go | 12 |
3 files changed, 142 insertions, 38 deletions
@@ -18,12 +18,13 @@ import ( var LocalMessages = message.Messages{} var DatabasePath = "infodump.db" var DB *sql.DB +var MessageCache string // Readline reads from a buffered stdin and returns the line func Readline() string { reader := bufio.NewReader(os.Stdin) line, _ := reader.ReadString('\n') - return line + return line[:len(line)-1] } // MenuElements is a list of options for the menu, consisting of a description and a function @@ -90,10 +91,8 @@ func main() { {"Start OLN Listener", StartOLNListener}, {"Read Messages", ReadMessages}, {"Write Message", WriteMessage}, - {"Sync Messages", SyncMessages}, - {"Set IPFS Gateway", SetIPFSGateway}, - {"Set Database", SetDatabase}, - {"Configure Followed Tags", ConfigureFollowedTags}, + {"Sync Messages", SyncMenu}, + {"Settings", SettingsMenu}, {"Quit", func() { os.Exit(0) }}, }) @@ -103,6 +102,33 @@ func main() { } } +// A submenu for all settings +func SettingsMenu() { + // Present the user with a menu + Menu([]MenuElements{ + {"Set IPFS Gateway", SetIPFSGateway}, + {"Set Database", SetDatabase}, + {"Configure Followed Tags", ConfigureFollowedTags}, + {"Back", func() {}}, + }) +} + +// A menu for the several parts of Sync: +// saving messages to the local database +// reading messages from the local database +// reading messages from the network +// writing messages to the network +func SyncMenu() { + // Present the user with a menu + Menu([]MenuElements{ + {"Save Messages to Database", SaveMessagesToDatabase}, + {"Read Messages from Database", ReadMessagesFromDatabase}, + {"Read Messages from Network", ReadMessagesFromNetwork}, + {"Write Messages to Network", WriteMessagesToNetwork}, + {"Back", func() {}}, + }) +} + // StartOLNListener starts a PubSub listener that listens for messages from the network // and adds them to LocalMessages // For this it uses the IPFS gateway and listens on the topic "OLN", as well as @@ -124,7 +150,7 @@ func StartOLNListener() { } subs = append(subs, olnsub) for _, tag := range followedTags { - tagssub, err := myIPFS.PubSubSubscribe("oln-tag-" + tag) + tagssub, err := myIPFS.PubSubSubscribe("oln-" + tag) if err != nil { fmt.Println(err) } else { @@ -197,29 +223,91 @@ func GetMessagesFromDatabase(db *sql.DB) *message.Messages { return &msgs } +// ReadMessages shows the messages in LocalMessages sorted by importance, 10 at a time func ReadMessages() { - // Show all messages in LocalMessages - fmt.Println("Local messages:") - LocalMessages.Each(func(m *message.Message) { - fmt.Println(m.String()) - }) + // Use LocalMessages to get the messages and get the sorted list of messages + // through the MessageList method + msgs := LocalMessages.MessageList() + // Loop through the messages and print them + for i, m := range msgs { + fmt.Println(m) + if i%10 == 9 { + fmt.Println("Press enter to continue... Type anything to stop") + contp := Readline() + if contp != "" { + return + } + } + } } func WriteMessage() { // Get a message and an urgency from the user. // The urgency is used to set the strength of the Proof of Work - fmt.Println("Enter a message: ") - m := Readline() + // If there is a message in the MessageCache, ask the user if they want to use it + // If there is no message in the MessageCache, ask the user to write a message + var m string + if MessageCache != "" { + fmt.Println("You wrote a message before that you didn't send yet. Do you want to use that message?") + fmt.Println("The message is:", MessageCache) + fmt.Println("Type 'yes' to use the message, or anything else to write a new message") + usep := Readline() + if usep == "yes" { + fmt.Println("Using message from cache") + m = MessageCache + } else { + fmt.Println("Writing new message") + m = usep + } + } else { + fmt.Println("Write a message:") + m = Readline() + } fmt.Println("Enter an urgency (higher is stronger but takes longer to produce): ") var urgency int fmt.Scanln(&urgency) - // Create a Message object - msg := message.New(m, urgency, time.Now().Unix()) + fmt.Println("How many seconds should we wait for the POW to be done? (default is 5): ") + var powtime int + fmt.Scanln(&powtime) + if powtime == 0 { + powtime = 5 + } + // Create a new message object + msg, err := message.New(m, urgency, time.Now().Unix(), time.Duration(powtime)*time.Second) + if err != nil { + fmt.Println(err) + fmt.Println("Want to try again with another urgency or timeout? (y/n)") + contp := Readline() + if contp == "y" { + MessageCache = m + WriteMessage() + } + return + } + // MessageCache can be discarded after this point + MessageCache = "" // Add the message to LocalMessages LocalMessages.Add(msg) + + // Ask if the user wants to write another message or save the messages to the database + fmt.Println("Do you want to write another message? (y/n)") + contp := Readline() + if contp == "y" { + WriteMessage() + } else { + fmt.Println("Do you want to save the messages to the database? (y/n)") + contp := Readline() + if contp == "y" { + SaveMessagesToDatabase() + } + } } -func SyncMessages() { +// Implementing the Sync Menu options +// SaveMessagesToDatabase, ReadMessagesFromDatabase, ReadMessagesFromNetwork and WriteMessagesToNetwork + +// SaveMessagesToDatabase saves the messages in LocalMessages to the database +func SaveMessagesToDatabase() { // Update the database with the messages in LocalMessages db := GetDatabase() // Put the messages in the database @@ -228,26 +316,34 @@ func SyncMessages() { if err != nil { fmt.Println(err) } else { - fmt.Println("Message", m.Stamp(), "synced") + fmt.Println("Message", m.Stamp(), "saved to database") } }) +} - fmt.Println("Now loading messages from database...") +// ReadMessagesFromDatabase reads the messages from the database and adds them to LocalMessages +func ReadMessagesFromDatabase() { // Get the messages from the database - messages := GetMessagesFromDatabase(db) + messages := GetMessagesFromDatabase(GetDatabase()) + // Add the messages to LocalMessages + LocalMessages.AddMany(messages) +} - fmt.Println("Messages loaded from database") +// ReadMessagesFromNetwork reads the messages from the IPFS network and adds them to LocalMessages +func ReadMessagesFromNetwork() { + // Get the messages from the IPFS network + // TODO: Implement this +} + +// WriteMessagesToNetwork writes the messages in LocalMessages to the IPFS network +func WriteMessagesToNetwork() { // Add the messages to the IPFS network - cid, err := messages.AddToIPFS() + cid, err := LocalMessages.AddToIPFS() if err != nil { fmt.Println(err) } else { fmt.Println("Messages synced to IPFS: ", cid) } - - // Set LocalMessages to the messages that are in the database - LocalMessages = message.Messages{} - LocalMessages.AddMany(messages) } func TestIPFSGateway(gateway string) error { @@ -299,7 +395,7 @@ func SetDatabase() { fmt.Println("Database path: ", DatabasePath) fmt.Println("Is this correct? (y/n)") answer := Readline() - if strings.HasPrefix(answer, "n") { + if answer == "n" { fmt.Println("Enter the database path: ") DatabasePath = Readline() } @@ -313,7 +409,7 @@ func SetDatabase() { if DB != nil { fmt.Println("Database already set, overwrite? (y/n)") answer := Readline() - if strings.HasPrefix(answer, "n") { + if answer == "n" { return } } @@ -321,7 +417,7 @@ func SetDatabase() { if _, err := os.Stat(DatabasePath); os.IsNotExist(err) { fmt.Println("Database does not exist, create? (y/n)") answer := Readline() - if strings.HasPrefix(answer, "n") { + if answer == "n" { return } } diff --git a/message/message.go b/message/message.go index 0c5af56..7a1699d 100644 --- a/message/message.go +++ b/message/message.go @@ -64,11 +64,14 @@ func (m *Messages) MessageList() []*Message { } // Proof of Work: Find the nonce for a message by hashing the message and checking for at least n initial zeroes in the binary representation of the resulting hash -func (msg *Message) ProofOfWork(n int) { +// If it takes too long, return an error +func (msg *Message) ProofOfWork(n int, timeout time.Duration) error { // Create a local copy of the message and start counting m := *msg m.Nonce = 0 + start := time.Now() // Loop until we find a nonce that satisfies the proof of work + // If the nonce is not found within the timeout, return an error for { // Increment the nonce and hash the message m.Nonce++ @@ -77,9 +80,14 @@ func (msg *Message) ProofOfWork(n int) { if CountLeadingZeroes(hash) >= n { break } + // If the nonce is not found within the timeout, return an error + if time.Since(start) > timeout { + return fmt.Errorf("proof of work timed out") + } } // Set the message to the local copy *msg = m + return nil } // Get the SHA256 hash of a message plus the timestamp plus the nonce as a byte slice @@ -115,10 +123,10 @@ func (m *Message) Lead() int { return CountLeadingZeroes(m.Hash()) } -func New(msg string, n int, timestamp int64) *Message { +func New(msg string, n int, timestamp int64, timeout time.Duration) (*Message, error) { m := Message{Message: msg, Timestamp: timestamp} - m.ProofOfWork(n) - return &m + err := m.ProofOfWork(n, timeout) + return &m, err } // Map Messages maps the stamp of the message to the message itself diff --git a/message/message_test.go b/message/message_test.go index 06f1bc7..be2b233 100644 --- a/message/message_test.go +++ b/message/message_test.go @@ -8,11 +8,11 @@ import ( "git.kiefte.eu/lapingvino/infodump/message" ) -// Test if the code finishes in time +// Test if creating a proof of work of 16 leading zeros finishes in 10 seconds func TestMessageTimeout(t *testing.T) { - time.AfterFunc(10*time.Second, func() { - t.Error("Test timed out") - }) - _ = message.New("Hello World!", 16, time.Now().Unix()) - // Success + msg := message.Message{Message: "test", Timestamp: time.Now().Unix()} + err := msg.ProofOfWork(16, 10*time.Second) + if err != nil { + t.Error(err) + } } |