better difficulty

main
Bill Mill 2 years ago
parent 5ac47534f7
commit b9f9ee38e5
  1. 48
      server/main.go

@ -1,12 +1,10 @@
// https://github.com/robinsloan/spring-83-spec/blob/main/draft-20220609.md // https://github.com/robinsloan/spring-83-spec/blob/main/draft-20220609.md
// TODO: // TODO:
// * wipe expired posts // * wipe expired posts
// * add difficulty checking
// * check that the body contains a proper last-modified tag // * check that the body contains a proper last-modified tag
// * implement peer sharing and receiving // * implement peer sharing and receiving
// * display HTML safely, and in shadow DOMs // * display HTML safely (strip javascript with sanitize API maybe?)
// * right now we just don't allow actual HTML, which is of course // * add /<key> to show a single board
// against the spirit of the thing
package main package main
import ( import (
@ -165,6 +163,17 @@ func (s *Spring83Server) boardCount() (int, error) {
return count, nil return count, nil
} }
func (s *Spring83Server) getDifficulty() (float64, uint64, error) {
count, err := s.boardCount()
if err != nil {
return 0, 0, err
}
difficultyFactor := math.Pow(float64(count)/10_000_000, 4)
keyThreshold := uint64(MAX_SIG * (1.0 - difficultyFactor))
return difficultyFactor, keyThreshold, nil
}
func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) { func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Spring-Version", "83") w.Header().Set("Spring-Version", "83")
@ -214,15 +223,14 @@ func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) {
// apply another check. The key, interpreted as a 256-bit number, must be // apply another check. The key, interpreted as a 256-bit number, must be
// less than a threshold defined by the server's difficulty factor: // less than a threshold defined by the server's difficulty factor:
if curBoard == nil { if curBoard == nil {
count, err := s.boardCount() difficultyFactor, keyThreshold, err := s.getDifficulty()
if err != nil { if err != nil {
log.Printf(err.Error()) log.Printf(err.Error())
http.Error(w, "internal error", http.StatusInternalServerError) http.Error(w, "internal error", http.StatusInternalServerError)
return return
} }
difficultyFactor := math.Pow(float64(count)/10_000_000, 4)
w.Header().Add("Spring-Difficulty", fmt.Sprintf("%f", difficultyFactor)) w.Header().Add("Spring-Difficulty", fmt.Sprintf("%f", difficultyFactor))
keyThreshold := MAX_SIG * (1.0 - difficultyFactor)
// Using that difficulty factor, we can calculate the key threshold: // Using that difficulty factor, we can calculate the key threshold:
// //
@ -231,7 +239,7 @@ func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) {
// //
// The server must reject PUT requests for new keys that are not less // The server must reject PUT requests for new keys that are not less
// than <an inscrutable gigantic number> // than <an inscrutable gigantic number>
if binary.BigEndian.Uint64(key) >= uint64(keyThreshold) { if binary.BigEndian.Uint64(key) >= keyThreshold {
if err != nil || len(key) != 32 { if err != nil || len(key) != 32 {
// the spec doesn't specify the proper return value in this case // the spec doesn't specify the proper return value in this case
http.Error(w, "Key greater than threshold", http.StatusBadRequest) http.Error(w, "Key greater than threshold", http.StatusBadRequest)
@ -292,7 +300,6 @@ func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) {
if keyStr[58:60] != "ed" || if keyStr[58:60] != "ed" ||
(last4 != time.Now().Format("2006") && (last4 != time.Now().Format("2006") &&
last4 != time.Now().AddDate(1, 0, 0).Format("2006")) { last4 != time.Now().AddDate(1, 0, 0).Format("2006")) {
log.Printf("%s %s %s", keyStr[58:60] == "ed", last4 == time.Now().Format("2006"), time.Now().Format("2006"))
http.Error(w, "Signature must end with edYYYY", http.StatusBadRequest) http.Error(w, "Signature must end with edYYYY", http.StatusBadRequest)
return return
} }
@ -305,19 +312,6 @@ func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) {
return return
} }
// TODO:
// Additionally, if the server doesn't have any board
// stored for <key>, then it must apply another check. The
// key, interpreted as a 256-bit number, must be less than
// a threshold defined by the server's difficulty factor:
//
// MAX_SIG = (2**256 - 1) key_threshold = MAX_SIG * ( 1.0 -
// difficulty_factor)
//
// This check is not applied to keys for which the server
// already has a board stored. You can read more about the
// difficulty factor later in this document.
expiry := time.Now().AddDate(0, 0, 7).Format(time.RFC3339) expiry := time.Now().AddDate(0, 0, 7).Format(time.RFC3339)
_, err = s.db.Exec(` _, err = s.db.Exec(`
INSERT INTO boards (key, board, expiry) INSERT INTO boards (key, board, expiry)
@ -373,6 +367,7 @@ func (s *Spring83Server) loadBoards() ([]Board, error) {
return boards, nil return boards, nil
} }
// for now, on loads to /, I'm just going to show all boards no matter what
func (s *Spring83Server) showBoard(w http.ResponseWriter, r *http.Request) { func (s *Spring83Server) showBoard(w http.ResponseWriter, r *http.Request) {
boards, err := s.loadBoards() boards, err := s.loadBoards()
if err != nil { if err != nil {
@ -381,6 +376,15 @@ func (s *Spring83Server) showBoard(w http.ResponseWriter, r *http.Request) {
return return
} }
difficultyFactor, _, err := s.getDifficulty()
if err != nil {
log.Printf(err.Error())
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
w.Header().Add("Spring-Difficulty", fmt.Sprintf("%f", difficultyFactor))
boardBytes, err := json.Marshal(boards) boardBytes, err := json.Marshal(boards)
if err != nil { if err != nil {
log.Printf(err.Error()) log.Printf(err.Error())

Loading…
Cancel
Save