aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoop Kiefte <ikojba@gmail.com>2021-12-12 02:44:11 +0000
committerGitHub <noreply@github.com>2021-12-12 02:44:11 +0000
commit407a75942f8bb7758f40bb04714d2ff0964972e1 (patch)
tree18f671d672e4eecd00ad650fe6701bc44ef9eeff
parent7f41a498b057d2ab180d288f212e0adc498e203d (diff)
Implemented paging and improved POW calculation
-rw-r--r--main.go152
-rw-r--r--message/message.go16
-rw-r--r--message/message_test.go12
3 files changed, 142 insertions, 38 deletions
diff --git a/main.go b/main.go
index 284709d..b88e710 100644
--- a/main.go
+++ b/main.go
@@ -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)
+ }
}