diff --git a/api_server/api_server.go b/api_server/api_server.go index 1e68dd9..f7b3de4 100644 --- a/api_server/api_server.go +++ b/api_server/api_server.go @@ -36,14 +36,19 @@ func (s *ApiServer) publishHandler(w rest.ResponseWriter, req *rest.Request) { input := schema.Np2pEventForREST{} err := req.DecodeJsonPayload(&input) + if err != nil { + fmt.Println(err) + rest.Error(w, err.Error(), http.StatusBadRequest) + return + } + if glo_val.DenyWriteMode { rest.Error(w, "Write is denied", http.StatusNotAcceptable) return } - if err != nil { - fmt.Println(err) - rest.Error(w, err.Error(), http.StatusBadRequest) + if input.Verify() == false { + rest.Error(w, "Invalid Sig", http.StatusBadRequest) return } @@ -163,13 +168,13 @@ func (s *ApiServer) setOrUpdateFollowList(w rest.ResponseWriter, input *schema.N func (s *ApiServer) sendReaction(w rest.ResponseWriter, input *schema.Np2pEventForREST) { evt := schema.NewNp2pEventFromREST(input) - err := s.buzzPeer.MessageMan.UnicastEventData(evt.Tags["p"][0].(string), evt) - if err != nil && evt.Tags["p"][0].(string) != glo_val.SelfPubkeyStr { + err := s.buzzPeer.MessageMan.UnicastEventData(string((*(schema.FindFirstSpecifiedTag(&evt.Tags, "p")))[1]), evt) + if err != nil && string((*(schema.FindFirstSpecifiedTag(&evt.Tags, "p")))[1]) != glo_val.SelfPubkeyStr { // destination server is offline // so add event to retry queue // except destination is myself case - s.buzzPeer.MessageMan.DataMan.AddReSendNeededEvent([]uint64{np2p_util.Get6ByteUint64FromHexPubKeyStr(evt.Tags["p"][0].(string))}, evt, true) - fmt.Println(evt.Tags["p"][0].(string)) + s.buzzPeer.MessageMan.DataMan.AddReSendNeededEvent([]uint64{np2p_util.Get6ByteUint64FromHexPubKeyStr(string((*(schema.FindFirstSpecifiedTag(&evt.Tags, "p")))[0]))}, evt, true) + fmt.Println(string((*(schema.FindFirstSpecifiedTag(&evt.Tags, "p")))[1])) fmt.Println(err) } diff --git a/core/data_manager.go b/core/data_manager.go index 236e573..e5c1abf 100644 --- a/core/data_manager.go +++ b/core/data_manager.go @@ -53,11 +53,13 @@ func (dman *DataManager) StoreEvent(evt *schema.Np2pEvent) { // log event data when it is not duplicated // write asynchrounously if evt.Tags != nil { - // consider when func is called from recovery - if _, ok2 := evt.Tags["recovering"]; ok2 { - delete(evt.Tags, "recovering") - if len(evt.Tags) == 0 { + tagsLen := len(evt.Tags) + if tagsLen != 0 && string(evt.Tags[tagsLen-1][0]) == "recovering" { + // consider when func is called from recovery + if tagsLen == 1 { evt.Tags = nil + } else { + evt.Tags = evt.Tags[:tagsLen-1] } return } diff --git a/core/message_manager.go b/core/message_manager.go index 903983d..712237e 100644 --- a/core/message_manager.go +++ b/core/message_manager.go @@ -117,6 +117,12 @@ func (mm *MessageManager) handleRecvMsgUnicast(src uint64, pkt *schema.Np2pPacke for _, evt := range pkt.Events { // handle response of request + if evt.Verify() == false { + // invalid signiture + fmt.Println("invalid signiture") + continue + } + // store received event data (on memory) mm.DataMan.StoreEvent(evt) diff --git a/core/np2p_peer.go b/core/np2p_peer.go index b618f10..94c3f7b 100644 --- a/core/np2p_peer.go +++ b/core/np2p_peer.go @@ -87,6 +87,12 @@ func (p *Np2pPeer) OnRecvBroadcast(src uint64, buf []byte) (received schema.Enco if pkt.Events != nil { for _, evt := range pkt.Events { if _, ok := p.recvedEvtReqMap[np2p_util.ExtractUint64FromBytes(evt.Id[:])]; !ok { + if evt.Verify() == false { + // invalid signiture + fmt.Println("invalid signiture") + continue + } + err2 := p.MessageMan.handleRecvMsgBcastEvt(src, pkt, evt) if err2 != nil { panic(err2) diff --git a/core/recovery_manager.go b/core/recovery_manager.go index 7c36e0f..0986b61 100644 --- a/core/recovery_manager.go +++ b/core/recovery_manager.go @@ -27,10 +27,10 @@ func (rm *RecoveryManager) Recover() { for err == nil { evt, err_ := schema.NewNp2pEventFromBytes(buf) if evt.Tags != nil { - evt.Tags["recovering"] = []interface{}{true} + evt.Tags = append(evt.Tags, []schema.TagElem{schema.TagElem("recovering")}) } else { - evt.Tags = make(map[string][]interface{}) - evt.Tags["recovering"] = []interface{}{true} + evt.Tags = make([][]schema.TagElem, 0) + evt.Tags = append(evt.Tags, []schema.TagElem{schema.TagElem("recovering")}) } if err_ != nil { // EOF diff --git a/schema/np2p_event.go b/schema/np2p_event.go index 968a441..08da46f 100644 --- a/schema/np2p_event.go +++ b/schema/np2p_event.go @@ -7,14 +7,17 @@ import ( "math/big" ) +type TagElem []byte + type Np2pEvent struct { Id [np2p_const.EventIdSize]byte // 32-bytes integer (sha256 32bytes hash) Pubkey [np2p_const.PubkeySize]byte // encoded 256bit uint (holiman/uint256) Created_at int64 // unix timestamp in seconds Kind uint16 // integer between 0 and 65535 - Tags map[string][]interface{} // Key: tag string, Value: any type - Content string - Sig *[np2p_const.SignatureSize]byte // 64-bytes integr of the signature of the sha256 hash of the serialized event data + //Tags map[string][]interface{} // Key: tag string, Value: any type + Tags [][]TagElem // each element is byte array. when original value is string, it is converted to []byte + Content string + Sig *[np2p_const.SignatureSize]byte // 64-bytes integr of the signature of the sha256 hash of the serialized event data } func (e *Np2pEvent) GetPubkey() *big.Int { @@ -38,6 +41,11 @@ func (e *Np2pEvent) Encode() []byte { return b } +func (evt *Np2pEvent) Verify() bool { + restFormEvt := NewNp2pEventForREST(evt) + return restFormEvt.Verify() +} + func NewNp2pEventFromBytes(b []byte) (*Np2pEvent, error) { var e Np2pEvent if err := msgpack.Unmarshal(b, &e); err != nil { @@ -46,8 +54,3 @@ func NewNp2pEventFromBytes(b []byte) (*Np2pEvent, error) { //fmt.Println(e) return &e, nil } - -func Verify(evt *Np2pEvent) bool { - restFormEvt := NewNp2pEventForREST(evt) - return restFormEvt.Verify() -} diff --git a/schema/np2p_event_rest.go b/schema/np2p_event_rest.go index 70b41aa..2c7bb1b 100644 --- a/schema/np2p_event_rest.go +++ b/schema/np2p_event_rest.go @@ -2,7 +2,6 @@ package schema import ( "encoding/hex" - "fmt" "github.com/nbd-wtf/go-nostr" "github.com/ryogrid/nostrp2p/np2p_util" ) @@ -18,7 +17,6 @@ type Np2pEventForREST struct { } func NewNp2pEventForREST(evt *Np2pEvent) *Np2pEventForREST { - //idStr := fmt.Sprintf("%x", evt.Id[:]) idStr := hex.EncodeToString(evt.Id[:]) pubkeyStr := hex.EncodeToString(evt.Pubkey[:]) sigStr := "" @@ -27,13 +25,10 @@ func NewNp2pEventForREST(evt *Np2pEvent) *Np2pEventForREST { } tagsArr := make([][]string, 0) - for k, v := range evt.Tags { + for _, v := range evt.Tags { tmpArr := make([]string, 0) - r := []rune(k) - // remove duplicated tag suffix (ex: "p_0" -> "p") - tmpArr = append(tmpArr, string(r[0])) - for _, val := range v { - tmpArr = append(tmpArr, val.(string)) + for _, vv := range v { + tmpArr = append(tmpArr, string(vv)) } tagsArr = append(tagsArr, tmpArr) } @@ -50,22 +45,15 @@ func NewNp2pEventForREST(evt *Np2pEvent) *Np2pEventForREST { } func NewNp2pEventFromREST(evt *Np2pEventForREST) *Np2pEvent { - tagsMap := make(map[string][]interface{}) - tagCntMap := make(map[string]int) - for _, tag := range evt.Tags { - vals := make([]interface{}, 0) - for _, val := range tag[1:] { - vals = append(vals, val) + tagsList := make([][]TagElem, 0) + if evt.Tags != nil { + for _, tagList := range evt.Tags { + elems := make([]TagElem, 0) + for _, elem := range tagList { + elems = append(elems, TagElem(elem)) + } + tagsList = append(tagsList, elems) } - if _, ok := tagCntMap[tag[0]]; ok { - tagCntMap[tag[0]]++ - tag[0] = fmt.Sprintf("%s_%d", tag[0], tagCntMap[tag[0]]) - tagsMap[tag[0]] = vals - } else { - tagCntMap[tag[0]] = 0 - tagsMap[tag[0]] = vals - } - } pkey, err := hex.DecodeString(evt.Pubkey) @@ -94,7 +82,7 @@ func NewNp2pEventFromREST(evt *Np2pEventForREST) *Np2pEvent { Id: evtId32, //evtId.Bytes32(), Created_at: evt.Created_at, Kind: evt.Kind, - Tags: tagsMap, + Tags: tagsList, Content: evt.Content, Sig: &sigBytes, } diff --git a/schema/schema_util.go b/schema/schema_util.go new file mode 100644 index 0000000..f41117c --- /dev/null +++ b/schema/schema_util.go @@ -0,0 +1,11 @@ +package schema + +func FindFirstSpecifiedTag(tags *[][]TagElem, tag string) *[]TagElem { + for _, t := range *tags { + if string(t[0]) == tag { + tmpVal := t + return &tmpVal + } + } + return nil +}