diff --git a/contrib/codecs/rdwr/client.go b/contrib/codecs/rdwr/client.go
index 0cf77e5fb346bf786cbe8068e20c7b0ef671d10e..8943e8fe43e654a6ea208dfa4fbf703f695fa811 100644
--- a/contrib/codecs/rdwr/client.go
+++ b/contrib/codecs/rdwr/client.go
@@ -73,7 +73,7 @@ func (c *Client) listen() error {
 	defer jx.PutDecoder(jd)
 	jd.Reset(c.rd)
 	for {
-		msg, err := jd.RawAppend(nil)
+		msg, err := jd.Raw()
 		if err != nil {
 			return err
 		}
diff --git a/pkg/clientutil/idreply.go b/pkg/clientutil/idreply.go
index 167ce521046d656894ffcae672c926ddd5ab8cc0..d0cb60206b57398dd332a17b151562e7d0ee3af7 100644
--- a/pkg/clientutil/idreply.go
+++ b/pkg/clientutil/idreply.go
@@ -21,7 +21,7 @@ type IdReply struct {
 }
 
 type msgOrError struct {
-	msg io.ReadCloser
+	msg io.Reader
 	err error
 }
 
@@ -74,7 +74,7 @@ func (i *IdReply) remove(id []byte) {
 	delete(i.chs, string(id))
 }
 
-func (i *IdReply) Resolve(id []byte, msg io.ReadCloser, err error) {
+func (i *IdReply) Resolve(id []byte, msg io.Reader, err error) {
 	ch := i.makeOrTake(id)
 	if ch == nil {
 		return
@@ -92,7 +92,7 @@ func (i *IdReply) Resolve(id []byte, msg io.ReadCloser, err error) {
 
 }
 
-func (i *IdReply) Ask(ctx context.Context, id []byte) (io.ReadCloser, error) {
+func (i *IdReply) Ask(ctx context.Context, id []byte) (io.Reader, error) {
 	select {
 	case resp := <-i.makeOrTake(id):
 		return resp.msg, resp.err
diff --git a/pkg/jsonrpc/json.go b/pkg/jsonrpc/json.go
index 30513769df698cf67dd7e731e714a2c499fd3fb7..b1b687347a478506a49aac30ad9865c1681c8643 100644
--- a/pkg/jsonrpc/json.go
+++ b/pkg/jsonrpc/json.go
@@ -89,7 +89,7 @@ func MarshalMessage(m *Message, enc *jx.Encoder) (err error) {
 	return nil
 }
 
-func UnmarshalMessage(m *Message, dec *jx.Decoder) error {
+func UnmarshalMessage(m *Message, dec *jx.Decoder, doCopy bool) error {
 	err := dec.Obj(func(d *jx.Decoder, key string) (err error) {
 		switch key {
 		default:
@@ -97,6 +97,9 @@ func UnmarshalMessage(m *Message, dec *jx.Decoder) error {
 			if err != nil {
 				return err
 			}
+			if doCopy {
+				raw = append([]byte(nil), raw...)
+			}
 			if m.Extensions == nil {
 				m.Extensions = make(map[string]json.RawMessage)
 			}
@@ -123,17 +126,22 @@ func UnmarshalMessage(m *Message, dec *jx.Decoder) error {
 		case "method":
 			m.Method, err = d.Str()
 		case "params":
-			val, err := d.RawAppend(nil)
+			val, err := d.Raw()
 			if err != nil {
 				return err
 			}
+			if doCopy {
+				val = append([]byte(nil), val...)
+			}
 			m.Params = json.RawMessage(val)
 		case "result":
-			// allocate full result :)
-			val, err := d.RawAppend(nil)
+			val, err := d.Raw()
 			if err != nil {
 				return err
 			}
+			if doCopy {
+				val = append([]byte(nil), val...)
+			}
 			m.Result = io.NopCloser(bytes.NewBuffer(val))
 		case "error":
 			val, err := d.Raw()
@@ -158,7 +166,7 @@ func (m *Message) UnmarshalJSON(xs []byte) error {
 	dec := jx.GetDecoder()
 	defer jx.PutDecoder(dec)
 	dec.ResetBytes(xs)
-	return UnmarshalMessage(m, dec)
+	return UnmarshalMessage(m, dec, true)
 }
 
 func (m Message) MarshalJSON() ([]byte, error) {
@@ -220,18 +228,22 @@ func IsBatchMessage(raw json.RawMessage) bool {
 // is called. Any non-JSON-RPC messages in the input return the zero value of
 // Message.
 func ParseMessage(in json.RawMessage) ([]*Message, bool) {
-	return ReadMessage(jx.DecodeBytes(in))
+	return ReadMessage(jx.DecodeBytes(in), true)
+}
+
+func ParseMessageCopyless(in json.RawMessage) ([]*Message, bool) {
+	return ReadMessage(jx.DecodeBytes(in), false)
 }
 
 // parseMessage parses raw bytes as a (batch of) JSON-RPC message(s). There are no error
 // checks in this function because the raw message has already been syntax-checked when it
 // is called. Any non-JSON-RPC messages in the input return the zero value of
 // Message.
-func ReadMessage(dec *jx.Decoder) ([]*Message, bool) {
+func ReadMessage(dec *jx.Decoder, doCopy bool) ([]*Message, bool) {
 	msgs := []*Message{{}}
 	switch dec.Next() {
 	case jx.Object:
-		_ = UnmarshalMessage(msgs[0], dec)
+		_ = UnmarshalMessage(msgs[0], dec, doCopy)
 		return msgs, false
 	default:
 		return msgs, false
@@ -239,12 +251,7 @@ func ReadMessage(dec *jx.Decoder) ([]*Message, bool) {
 		msgs = []*Message{}
 		dec.Arr(func(d *jx.Decoder) error {
 			msg := new(Message)
-			// err := UnmarshalMessage(msg, d)
-			raw, err := d.Raw()
-			if err != nil {
-				raw = []byte{}
-			}
-			err = json.Unmarshal(raw, msg)
+			err := UnmarshalMessage(msg, d, doCopy)
 			if err != nil {
 				msg = nil
 			}