func handleEntry(ctx *web.Context, hash string) { type entry struct { ChainID string Content string ExtIDs []string } e := new(entry) if entry, err := factomapi.EntryByHash(hash); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { e.ChainID = entry.ChainID.String() e.Content = hex.EncodeToString(entry.Content) for _, v := range entry.ExtIDs { e.ExtIDs = append(e.ExtIDs, hex.EncodeToString(v)) } } if p, err := json.Marshal(e); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func search(ctx *web.Context, collection string) { ctx.ContentType("json") ctx.SetHeader("Access-Control-Allow-Origin", "*", true) query := ctx.Params["query"] var limit, offset int64 var err error if limit, err = strconv.ParseInt(ctx.Params["limit"], 10, 32); err != nil { limit = 10 } if offset, err = strconv.ParseInt(ctx.Params["offset"], 10, 32); err != nil { offset = 0 } results, err := c.Search(collection, query, int(limit), int(offset)) buf := new(bytes.Buffer) encoder := json.NewEncoder(buf) if err != nil { encoder.Encode(err) ctx.WriteHeader(err.(*gorc.OrchestrateError).StatusCode) } else { encoder.Encode(results) } ctx.Write(buf.Bytes()) }
func handleDirectoryBlockHead(ctx *web.Context) { type dbhead struct { KeyMR string } h := new(dbhead) if block, err := factomapi.DBlockHead(); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { h.KeyMR = block.KeyMR.String() } if p, err := json.Marshal(h); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } // ctx.WriteHeader(httpOK) }
func responseJson(ctx *web.Context, statusCode int, obj interface{}) string { ctx.WriteHeader(statusCode) if obj != nil { content, _ := json.MarshalIndent(obj, " ", " ") return string(content) } return "" }
func renderTemplate(webContext *web.Context, template string, action string, context interface{}, statusCode int) { webContext.WriteHeader(statusCode) err := templates[template].ExecuteTemplate(webContext, action+".html", context) if err != nil { log.Println("[ERROR] renderTemplate: ", err) webContext.Abort(500, "Unable to process request.") } }
func HandleGetRaw(ctx *web.Context, hashkey string) { state := ctx.Server.Env["state"].(interfaces.IState) //TODO: var block interfaces.BinaryMarshallable d := new(RawData) h, err := primitives.HexToHash(hashkey) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } dbase := state.GetDB() var b []byte // try to find the block data in db and return the first one found if block, _ := dbase.FetchFBlockByKeyMR(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchDBlockByKeyMR(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchABlockByKeyMR(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchEBlockByKeyMR(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchECBlockByKeyMR(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchEntryByHash(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchFBlockByHash(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchDBlockByHash(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchABlockByHash(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchEBlockByHash(h); block != nil { b, _ = block.MarshalBinary() } else if block, _ := dbase.FetchECBlockByHash(h); block != nil { b, _ = block.MarshalBinary() } d.Data = hex.EncodeToString(b) if p, err := json.Marshal(d); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func handleGetFee(ctx *web.Context) { type x struct{ Fee int64 } b := new(x) b.Fee = int64(common.FactoidState.GetFactoshisPerEC()) if p, err := json.Marshal(b); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) return } else { ctx.Write(p) } }
func handleGetRaw(ctx *web.Context, hashkey string) { type rawData struct { Data string } //TODO: var block common.BinaryMarshallable d := new(rawData) h, err := common.HexToHash(hashkey) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } // try to find the block data in db and return the first one found if block, _ := dbase.FetchFBlockByHash(h); block != nil { bytes, _ := block.MarshalBinary() d.Data = hex.EncodeToString(bytes[:]) } else if block, _ := dbase.FetchDBlockByHash(h); block != nil { bytes, _ := block.MarshalBinary() d.Data = hex.EncodeToString(bytes[:]) } else if block, _ := dbase.FetchABlockByHash(h); block != nil { bytes, _ := block.MarshalBinary() d.Data = hex.EncodeToString(bytes[:]) } else if block, _ := dbase.FetchDBlockByMR(h); block != nil { bytes, _ := block.MarshalBinary() d.Data = hex.EncodeToString(bytes[:]) } else if block, _ := dbase.FetchEBlockByHash(h); block != nil { bytes, _ := block.MarshalBinary() d.Data = hex.EncodeToString(bytes[:]) } else if block, _ := dbase.FetchEBlockByMR(h); block != nil { bytes, _ := block.MarshalBinary() d.Data = hex.EncodeToString(bytes[:]) } else if block, _ := dbase.FetchECBlockByHash(h); block != nil { bytes, _ := block.MarshalBinary() d.Data = hex.EncodeToString(bytes[:]) } else if block, _ := dbase.FetchEntryByHash(h); block != nil { bytes, _ := block.MarshalBinary() d.Data = hex.EncodeToString(bytes[:]) } if p, err := json.Marshal(d); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } // ctx.WriteHeader(httpOK) }
/* Server a 500 Internal Error page Parameters: ctx: the context of the http request err: the error that was encountered */ func internalError(ctx *web.Context, err error) { logger.Printf("500 Internal Server Error: %v\n", err.Error()) sendEmailToAdmins("Redu.se Internal Error", err.Error()) ctx.WriteHeader(500) commonTemplate(ctx, "generic.html", map[string]string{"title_text": "500 Internal Server Error", "body_text": err.Error(), }) }
/* Serve a 404 Not Found error page Parameters: ctx: the context of the http request urlStr: the URL that the request was trying to access */ func error404(ctx *web.Context, urlStr string) { logger.Printf("404 Error for URL: %v\n", urlStr) bodyStr := "Could not locate \"" + urlStr + "\" on this server" ctx.WriteHeader(404) commonTemplate(ctx, "generic.html", map[string]string{"title_text": "404 Page Not Found", "body_text": bodyStr, }) }
// True is sccuess! False is failure. The Response is what the CLI // should report. func reportResults(ctx *web.Context, response string, success bool) { b := Response{ Response: response, Success: success, } if p, err := json.Marshal(b); err != nil { ctx.WriteHeader(httpBad) return } else { ctx.Write(p) } }
func handleProperties(ctx *web.Context) { r := new(common.Properties) r.Factomd_Version = common.FACTOMD_VERSION r.Protocol_Version = btcd.ProtocolVersion if p, err := json.Marshal(r); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func HandleCommitEntry(ctx *web.Context, name string) { data, err := ioutil.ReadAll(ctx.Request.Body) if err != nil { fmt.Println("Could not read from http request:", err) ctx.WriteHeader(httpBad) return } err = Wallet.CommitEntry(name, data) if err != nil { fmt.Println(err) ctx.WriteHeader(httpBad) return } }
func HandleGetFee(ctx *web.Context) { state := ctx.Server.Env["state"].(interfaces.IState) type x struct{ Fee int64 } b := new(x) b.Fee = int64(state.GetFactoidState().GetFactoshisPerEC()) if p, err := json.Marshal(b); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) return } else { ctx.Write(p) } }
func HandleDirectoryBlock(ctx *web.Context, hashkey string) { state := ctx.Server.Env["state"].(interfaces.IState) d := new(DBlock) h, err := primitives.HexToHash(hashkey) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } dbase := state.GetDB() block, err := dbase.FetchDBlockByKeyMR(h) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } if block == nil { block, err = dbase.FetchDBlockByHash(h) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } if block == nil { //TODO: Handle block not found return } } d.Header.PrevBlockKeyMR = block.GetHeader().GetPrevKeyMR().String() d.Header.SequenceNumber = block.GetHeader().GetDBHeight() d.Header.Timestamp = block.GetHeader().GetTimestamp() * 60 for _, v := range block.GetDBEntries() { l := new(EBlockAddr) l.ChainID = v.GetChainID().String() l.KeyMR = v.GetKeyMR().String() d.EntryBlockList = append(d.EntryBlockList, *l) } if p, err := json.Marshal(d); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func handleCommitChain(ctx *web.Context) { type commitchain struct { CommitChainMsg string } c := new(commitchain) if p, err := ioutil.ReadAll(ctx.Request.Body); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { if err := json.Unmarshal(p, c); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } } commit := common.NewCommitChain() if p, err := hex.DecodeString(c.CommitChainMsg); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { _, err := commit.UnmarshalBinaryData(p) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } } if err := factomapi.CommitChain(commit); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } // ctx.WriteHeader(httpOK) }
func handleRevealEntry(ctx *web.Context) { type revealentry struct { Entry string } e := new(revealentry) if p, err := ioutil.ReadAll(ctx.Request.Body); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { if err := json.Unmarshal(p, e); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } } entry := common.NewEntry() if p, err := hex.DecodeString(e.Entry); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { _, err := entry.UnmarshalBinaryData(p) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } } if err := factomapi.RevealEntry(entry); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } // ctx.WriteHeader(httpOK) }
func handleDirectoryBlock(ctx *web.Context, keymr string) { type eblockaddr struct { ChainID string KeyMR string } type dblock struct { Header struct { PrevBlockKeyMR string SequenceNumber uint32 Timestamp uint32 } EntryBlockList []eblockaddr } d := new(dblock) if block, err := factomapi.DBlockByKeyMR(keymr); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { d.Header.PrevBlockKeyMR = block.Header.PrevKeyMR.String() d.Header.SequenceNumber = block.Header.DBHeight d.Header.Timestamp = block.Header.Timestamp * 60 for _, v := range block.DBEntries { l := new(eblockaddr) l.ChainID = v.ChainID.String() l.KeyMR = v.KeyMR.String() d.EntryBlockList = append(d.EntryBlockList, *l) } } if p, err := json.Marshal(d); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } // ctx.WriteHeader(httpOK) }
func HandleDirectoryBlockHead(ctx *web.Context) { state := ctx.Server.Env["state"].(interfaces.IState) h := new(DBHead) h.KeyMR = state.GetPreviousDirectoryBlock().GetKeyMR().String() fmt.Println(h.KeyMR) if p, err := json.Marshal(h); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func handleDirectoryBlockHeight(ctx *web.Context) { type dbheight struct { Height int } h := new(dbheight) if block, err := factomapi.DBlockHead(); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { h.Height = int(block.Header.DBHeight) } if p, err := json.Marshal(h); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func handleChainHead(ctx *web.Context, chainid string) { type chead struct { ChainHead string } c := new(chead) if mr, err := factomapi.ChainHead(chainid); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { c.ChainHead = mr.String() } if p, err := json.Marshal(c); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func HandleChainHead(ctx *web.Context, hashkey string) { state := ctx.Server.Env["state"].(interfaces.IState) c := new(CHead) h, err := primitives.HexToHash(hashkey) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } dbase := state.GetDB() mr, err := dbase.FetchHeadIndexByChainID(h) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } if mr == nil { err := fmt.Errorf("Missing Chain Head") wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } c.ChainHead = mr.String() if p, err := json.Marshal(c); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func HandleEntry(ctx *web.Context, hashkey string) { state := ctx.Server.Env["state"].(interfaces.IState) e := new(EntryStruct) h, err := primitives.HexToHash(hashkey) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } dbase := state.GetDB() entry, err := dbase.FetchEntryByHash(h) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } if entry == nil { //TODO: Handle block not found return } e.ChainID = entry.GetChainIDHash().String() e.Content = hex.EncodeToString(entry.GetContent()) for _, v := range entry.ExternalIDs() { e.ExtIDs = append(e.ExtIDs, hex.EncodeToString(v)) } if p, err := json.Marshal(e); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
func unpack(ctx *web.Context, action func(*payload)) { flusher, _ := ctx.ResponseWriter.(http.Flusher) defer flusher.Flush() var v payload if body, err := ioutil.ReadAll(ctx.Request.Body); err == nil { defer ctx.Request.Body.Close() if err := json.Unmarshal(body, &v); err != nil { ctx.WriteHeader(400) ctx.Write(errorMsg("INSUFFICIENT PAYLOAD")) return } if !verify(v.Signature) { ctx.WriteHeader(403) ctx.Write(errorMsg("INVALID SIGNATURE")) return } action(&v) return } else { ctx.WriteHeader(400) ctx.Write(errorMsg(err.Error())) } }
// &key=<key>&name=<name or address>&amount=<amount> // If no amount is specified, a zero is returned. func getParams_(ctx *web.Context, params string, ec bool) ( trans fct.ITransaction, key string, name string, address fct.IAddress, amount int64, ok bool) { key = ctx.Params["key"] name = ctx.Params["name"] StrAmount := ctx.Params["amount"] if len(StrAmount) == 0 { StrAmount = "0" } if len(key) == 0 || len(name) == 0 { str := fmt.Sprintln("Missing Parameters: key='", key, "' name='", name, "' amount='", StrAmount, "'") reportResults(ctx, str, false) ok = false return } msg, valid := ValidateKey(key) if !valid { reportResults(ctx, msg, false) ok = false return } amount, err := strconv.ParseInt(StrAmount, 10, 64) if err != nil { str := fmt.Sprintln("Error parsing amount.\n", err) reportResults(ctx, str, false) ok = false return } // Get the transaction trans, err = getTransaction(ctx, key) if err != nil { reportResults(ctx, "Failure to locate the transaction", false) ok = false return } // Get the input/output/ec address. Which could be a name. First look and see if it is // a name. If it isn't, then look and see if it is an address. Someone could // do a weird Address as a name and fool the code, but that seems unlikely. // Could check for that some how, but there are many ways around such checks. if len(name) <= fct.ADDRESS_LENGTH { we := Wallet.GetRaw([]byte(fct.W_NAME), []byte(name)) if we != nil { address, err = we.(wallet.IWalletEntry).GetAddress() if we.(wallet.IWalletEntry).GetType() == "ec" { if !ec { reportResults(ctx, "Was Expecting a Factoid Address", false) ok = false return } } else { if ec { reportResults(ctx, "Was Expecting an Entry Credit Address", false) ok = false return } } if err != nil || address == nil { reportResults(ctx, "Should not get an error geting a address from a Wallet Entry", false) ok = false return } ok = true return } } if (!ec && !fct.ValidateFUserStr(name)) || (ec && !fct.ValidateECUserStr(name)) { reportResults(ctx, fmt.Sprintf("The address specified isn't defined or is invalid: %s", name), false) ctx.WriteHeader(httpBad) ok = false return } baddr := fct.ConvertUserStrToAddress(name) address = fct.NewAddress(baddr) ok = true return }
func HandleEntryBlock(ctx *web.Context, hashkey string) { state := ctx.Server.Env["state"].(interfaces.IState) e := new(EBlock) h, err := primitives.HexToHash(hashkey) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } dbase := state.GetDB() block, err := dbase.FetchEBlockByKeyMR(h) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } if block == nil { block, err = dbase.FetchEBlockByHash(h) if err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } if block == nil { //TODO: Handle block not found return } } e.Header.BlockSequenceNumber = block.GetHeader().GetEBSequence() e.Header.ChainID = block.GetHeader().GetChainID().String() e.Header.PrevKeyMR = block.GetHeader().GetPrevKeyMR().String() if dblock, err := dbase.FetchDBlockByHeight(block.GetHeader().GetDBHeight()); err == nil { e.Header.Timestamp = dblock.GetHeader().GetTimestamp() * 60 } // create a map of possible minute markers that may be found in the // EBlock Body mins := make(map[string]uint8) for i := byte(1); i <= 10; i++ { h := make([]byte, 32) h[len(h)-1] = i mins[hex.EncodeToString(h)] = i } estack := make([]EntryAddr, 0) for _, v := range block.GetBody().GetEBEntries() { if n, exist := mins[v.String()]; exist { // the entry is a minute marker. add time to all of the // previous entries for the minute t := e.Header.Timestamp + 60*uint32(n) for _, w := range estack { w.Timestamp = t e.EntryList = append(e.EntryList, w) } estack = make([]EntryAddr, 0) } else { l := new(EntryAddr) l.EntryHash = v.String() estack = append(estack, *l) } } if p, err := json.Marshal(e); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }
// Starts a computation, validates the matrix in POST. // If matrix data is missing, returns 400 Bad Request. // If on the other hand matrix is data is not missing, // but makes no sense, it returns 422 Unprocessable Entity. func (server *Server) PostMatrix(ctx *web.Context) { defer runtime.GC() // Parse params var paramBlob struct { Matrix []int `json:"matrix"` Country string `json:"country"` SpeedProfile float64 `json:"speed_profile"` } if err := json.NewDecoder(ctx.Request.Body).Decode(¶mBlob); err != nil { ctx.Abort(400, err.Error()) return } data := paramBlob.Matrix country := strings.ToLower(paramBlob.Country) sp := int(paramBlob.SpeedProfile) ok := len(data) > 0 && country != "" && sp > 0 if ok { // Sanitize speed profile. if !contains(sp, allowedSpeeds) { msg := fmt.Sprintf("speed profile '%d' makes no sense, must be one of %s", sp, fmt.Sprint(allowedSpeeds)) ctx.Abort(422, msg) return } // Sanitize country. if _, ok := server.AllowedCountries[country]; !ok { countries := "" for k := range server.AllowedCountries { countries += k + " " } ctx.Abort(422, "country "+country+" not allowed, must be one of: "+countries) return } matrix, err := server.Via.ComputeMatrix(data, country, sp) if err != nil { viaErr.NewError(viaErr.ErrMatrixComputation, err.Error()).WriteTo(ctx.ResponseWriter) return } result := Result{ Progress: "complete", Matrix: matrix, SpeedProfile: sp, } ctx.WriteHeader(200) ctx.ContentType("json") if err := json.NewEncoder(ctx.ResponseWriter).Encode(result); err != nil { viaErr.NewError(viaErr.ErrMatrixComputation, "Failed to encode results to response writer.").WriteTo(ctx.ResponseWriter) return } } else { body, _ := ioutil.ReadAll(ctx.Request.Body) ctx.Abort(400, "Missing or invalid matrix data, speed profile, or country. You sent: "+string(body)) return } }
func handleEntryBlock(ctx *web.Context, keymr string) { type entryaddr struct { EntryHash string Timestamp uint32 } type eblock struct { Header struct { BlockSequenceNumber uint32 ChainID string PrevKeyMR string Timestamp uint32 } EntryList []entryaddr } e := new(eblock) if block, err := factomapi.EBlockByKeyMR(keymr); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { e.Header.BlockSequenceNumber = block.Header.EBSequence e.Header.ChainID = block.Header.ChainID.String() e.Header.PrevKeyMR = block.Header.PrevKeyMR.String() if dblock, err := dbase.FetchDBlockByHeight(block.Header.DBHeight); err == nil { e.Header.Timestamp = dblock.Header.Timestamp * 60 } // create a map of possible minute markers that may be found in the // EBlock Body mins := make(map[string]uint8) for i := byte(1); i <= 10; i++ { h := make([]byte, 32) h[len(h)-1] = i mins[hex.EncodeToString(h)] = i } estack := make([]entryaddr, 0) for _, v := range block.Body.EBEntries { if n, exist := mins[v.String()]; exist { // the entry is a minute marker. add time to all of the // previous entries for the minute t := e.Header.Timestamp + 60*uint32(n) for _, w := range estack { w.Timestamp = t e.EntryList = append(e.EntryList, w) } estack = make([]entryaddr, 0) } else { l := new(entryaddr) l.EntryHash = v.String() estack = append(estack, *l) } } } if p, err := json.Marshal(e); err != nil { wsLog.Error(err) ctx.WriteHeader(httpBad) ctx.Write([]byte(err.Error())) return } else { ctx.Write(p) } }